Skip to content

Commit d1e5622

Browse files
author
Alphonse Van Assche
committed
Initial commit
1 parent 151240f commit d1e5622

File tree

10 files changed

+634
-0
lines changed

10 files changed

+634
-0
lines changed

Diff for: p2-update-checker/.project

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<projectDescription>
3+
<name>p2-update-checker</name>
4+
<comment></comment>
5+
<projects>
6+
</projects>
7+
<buildSpec>
8+
<buildCommand>
9+
<name>org.python.pydev.PyDevBuilder</name>
10+
<arguments>
11+
</arguments>
12+
</buildCommand>
13+
<buildCommand>
14+
<name>org.eclipse.linuxtools.rpm.rpmlint.rpmlintBuilder</name>
15+
<arguments>
16+
</arguments>
17+
</buildCommand>
18+
</buildSpec>
19+
<natures>
20+
<nature>org.python.pydev.pythonNature</nature>
21+
<nature>org.eclipse.linuxtools.rpm.rpmlint.rpmlintNature</nature>
22+
</natures>
23+
</projectDescription>

Diff for: p2-update-checker/.pydevproject

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<?eclipse-pydev version="1.0"?>
3+
4+
<pydev_project>
5+
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
6+
<path>/p2-update-checker/src</path>
7+
</pydev_pathproperty>
8+
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.5</pydev_property>
9+
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
10+
</pydev_project>

Diff for: p2-update-checker/README

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
This script currently don't work without a patched [1] p2 director application
2+
3+
[1] https://bugs.eclipse.org/bugs/show_bug.cgi?id=250116

Diff for: p2-update-checker/src/actions.py

+194
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
import commands
2+
import string
3+
from time import gmtime, strftime
4+
import sys, smtplib
5+
import os
6+
import re
7+
import utils
8+
import shutil
9+
import tempfile
10+
import config
11+
12+
"""
13+
Actions implement a unique interface, Python don't support interfaces natively but
14+
some API use internal implementation - maybe we can revamp this in a more Python way.
15+
16+
Interface Action:
17+
18+
DESCRIPTION = # a short description
19+
20+
def run(self, update, packager, distRelease):
21+
# return str(status)
22+
"""
23+
24+
25+
class WriteSpecfile:
26+
"""This action add a changelog entry, update Version and Release tag,
27+
and update some defines"""
28+
29+
DESCRIPTION = "Write Specfile Action"
30+
31+
def run(self, update, packager, distRelease):
32+
result = self._applyTemplate(update, packager, distRelease)
33+
self.outputFile = os.path.join(
34+
config.OUTPUT_DIR, packager.dist.ID,
35+
packager.name.replace(" ", "_"), distRelease.tag, update.packageName + ".spec")
36+
37+
utils.writeFile(self.outputFile, result, 'w')
38+
return "done"
39+
40+
def _applyTemplate(self, update, packager, distRelease):
41+
content = packager.dist.getSpecfileContent(update.packageName, distRelease.tag)
42+
p = re.compile('%changelog')
43+
part = p.split(content)
44+
specContent = part[0].strip()
45+
specChangelogEntries = part[1].strip()
46+
47+
# FIXME: It could be better to have a "reference" bundle (the one that give the package version)
48+
major, minor, micro, qualifier = utils.parseBundleVersion(update.bundles[0].version)
49+
50+
try:
51+
m = re.search("Epoch:(\ | \t).*([0-9].*)", specContent, re.IGNORECASE)
52+
epoch = m.group(2).strip()
53+
if epoch != "":
54+
epoch += ":"
55+
except:
56+
epoch = ""
57+
58+
m = re.search("Version:(\ |\t)+", specContent, re.IGNORECASE)
59+
g = m.group(0)
60+
specContent = re.sub("Version:.*", g + update.bundles[0].version, specContent, re.IGNORECASE)
61+
62+
m = re.search("Release:(\ |\t)+", specContent, re.IGNORECASE)
63+
g = m.group(0)
64+
specContent = re.sub("Release:(\ |\b|)+([0-9]|\.|_|[a-z])+", g + "1", specContent, re.IGNORECASE)
65+
66+
specContent = self._setDefineValue(specContent, "major", major)
67+
specContent = self._setDefineValue(specContent, "minor", minor)
68+
specContent = self._setDefineValue(specContent, "micro", micro)
69+
specContent = self._setDefineValue(specContent, "qualifier", qualifier)
70+
71+
# used in eclipse-pydev.spec
72+
specContent = self._setDefineValue(specContent, "maint", micro)
73+
# used in eclipse.spec
74+
specContent = self._setDefineValue(specContent, "eclipse_major", major)
75+
specContent = self._setDefineValue(specContent, "eclipse_minor", minor)
76+
specContent = self._setDefineValue(specContent, "eclipse_micro", micro)
77+
78+
template = "${SPEC_CONTENT}\n\n" \
79+
+ "%changelog\n" \
80+
+ "* ${DATE} ${PACKAGER} <${PACKAGER_MAIL}> ${EPOCH}${VERSION}-1\n" \
81+
+ "- bump to ${VERSION}\n\n" \
82+
+ "${CHANGELOG_ENTRIES}"
83+
84+
result = string.Template(template).safe_substitute(
85+
SPEC_CONTENT=specContent,
86+
DATE=strftime("%a %b %d %Y", gmtime()),
87+
VERSION=major + "." + minor + "." + micro,
88+
EPOCH=epoch,
89+
PACKAGER=packager.name,
90+
PACKAGER_MAIL=packager.mail,
91+
CHANGELOG_ENTRIES=specChangelogEntries)
92+
return result
93+
94+
def _setDefineValue(self, specContent, define, value):
95+
try:
96+
exp = "%define(\ |\t)+" + define + "(\ |\t)+"
97+
m = re.search(exp, specContent, re.IGNORECASE)
98+
g = m.group(0)
99+
return re.sub("%define(\ |\t)+"+ define + ".*", g + value, specContent, re.IGNORECASE)
100+
except:
101+
return specContent
102+
103+
104+
class SendMail:
105+
"""This action send email about new updates available
106+
upstream for they packages"""
107+
108+
DESCRIPTION = "Send Mail Action"
109+
110+
def run(self, update, packager, distRelease):
111+
content = ""
112+
113+
# one mail by update
114+
reminderStr = packager.id + "-" + distRelease.tag + "-" + update.packageName \
115+
+ "-" + update.bundles[0].version
116+
reminders = []
117+
try:
118+
if not os.path.exists(config.REMINDER_FILE):
119+
utils.writeFile(config.REMINDER_FILE, "# Remove this file if you will re-send mail alerts\n", "w")
120+
content = utils.readFile(config.REMINDER_FILE);
121+
reminders = content.splitlines()
122+
except:
123+
pass
124+
for r in reminders:
125+
if r == reminderStr:
126+
return "skipped"
127+
content += reminderStr + "\n"
128+
utils.writeFile(config.REMINDER_FILE, content, 'w')
129+
130+
toaddrs = packager.mail + "\n"
131+
subject = "Updates are available for %s \n" % update.packageName
132+
msg = "To: " + toaddrs + "\n"\
133+
+ "From: " + config.FROM_ADRS + "\n" \
134+
+ "Subject: " + subject + "\n" \
135+
+ "PACKAGE INFO:\n" \
136+
+ str(update) \
137+
+ "\nRELEASE INFO:\n" \
138+
+ str(distRelease)
139+
server = smtplib.SMTP(config.SMTP_HOSTNAME)
140+
server.sendmail(config.FROM_ADRS, toaddrs, msg)
141+
server.quit()
142+
return "done"
143+
144+
145+
class FedoraMakeSRPM:
146+
"""This action must be run after WriteSpecfile"""
147+
148+
DESCRIPTION = "Make SRPM Action"
149+
150+
def run(self, update, packager, distRelease):
151+
self._prepare(update, packager, distRelease)
152+
return "done"
153+
154+
def _prepare(self, update, packager, distRelease):
155+
# create tmp directory
156+
currentDir = commands.getoutput("pwd");
157+
tmpDir = tempfile.mkdtemp("%s-%s_srpm" % (config.APP_NAME, update.packageName))
158+
os.chdir(tmpDir)
159+
cvsDir = "%s/%s" % (update.packageName, distRelease.tag)
160+
161+
# get sources
162+
status = os.system("CVSROOT=:pserver:[email protected]:/cvs/pkgs cvs co %s" % cvsDir)
163+
if status != 0:
164+
raise
165+
166+
# os.chdir(cvsDir)
167+
status = os.system("make -C %s" % cvsDir)
168+
if status != 0:
169+
raise
170+
171+
major, minor, micro, qualifier = utils.parseBundleVersion(update.bundles[0].version)
172+
173+
specWriter = WriteSpecfile()
174+
specWriter.run(update, packager, distRelease)
175+
specContent = utils.readFile(specWriter.outputFile)
176+
try:
177+
m = re.search("source[0|:].*[\ |\t]+(.*)", specContent, re.IGNORECASE)
178+
src_url = m.group(1)
179+
src_url = src_url.replace("%{major}", major)
180+
src_url = src_url.replace("%{minor}", minor)
181+
src_url = src_url.replace("%{micro}", micro)
182+
# fix eclipse-pydev define??
183+
src_url = src_url.replace("%{maint}", micro)
184+
status = os.system("wget %s" % src_url)
185+
if status != 0:
186+
raise
187+
status = os.system("make -C %s srpm" % cvsDir)
188+
if status != 0:
189+
raise
190+
except:
191+
# try to grab sources using fetch-* scripts??
192+
raise
193+
os.chdir(currentDir)
194+

Diff for: p2-update-checker/src/config.py

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import distFedora
2+
import actions
3+
import entity
4+
import logging
5+
6+
APP_NAME = "p2UpdateChecker"
7+
APP_DEBUG = False
8+
9+
LOG = logging.getLogger(APP_NAME)
10+
LOG_LEVEL = logging.DEBUG
11+
12+
P2_UPDATE_CMD = "java -cp %s org.eclipse.core.launcher.Main -application org.eclipse.equinox.p2.director.app.application -updatelist | uniq"
13+
OSGIDEPS_CMD = "find %s -type f | egrep '*.jar|*.MF' | /usr/lib/rpm/osgideps.pl -p | uniq"
14+
15+
OUTPUT_DIR = "output"
16+
17+
# Send Mail action configuration
18+
REMINDER_FILE = OUTPUT_DIR + "/alert_reminder.log"
19+
FROM_ADRS = "[email protected]"
20+
SMTP_HOSTNAME= "localhost"
21+
22+
# CHROOT="/var/lib/mock/fedora-rawhide-i386/root"
23+
CHROOT = ""
24+
RELEASES = []
25+
RELEASES.append(entity.DistribRelease(
26+
"rawhide",
27+
"devel",
28+
"%s/usr/lib64/eclipse/startup.jar" % CHROOT,
29+
"%s/usr/share/eclipse/dropins/ %s/usr/lib64/eclipse/dropins/" % (CHROOT, CHROOT),
30+
"fedora-rawhide-i386"))
31+
32+
# Distrib config
33+
DISTRIB = distFedora.Distrib(RELEASES)
34+
PROCESS = distFedora.Process()
35+
ACTIONS = [actions.WriteSpecfile(), actions.SendMail()]

Diff for: p2-update-checker/src/distExample.py

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
2+
PACKAGERS = []
3+
PACKAGERS.append(entity.Packager("userid", "username", "mail", DISTRIB, "eclipse-pydev"))
4+
5+
"""
6+
A Simple process implementation
7+
"""
8+
class ExampleProcess:
9+
10+
DESCRIPTION = "Example process"
11+
12+
def run(self, pkgsToUpdate, distRelease):
13+
for pkgToUpdate in pkgsToUpdate:
14+
for packager in PACKAGERS:
15+
packagerPackages = packager.packages.split(" ");
16+
for pkg in packagerPackages:
17+
if pkg.strip() == pkgToUpdate.packageName.strip():
18+
for action in ACTIONS:
19+
actionOutput = action.run(pkgToUpdate, packager, distRelease)
20+
msg = "%s (%s) for %s [%s]" % (action.DESCRIPTION, pkgToUpdate.packageName, packager.name, actionOutput)
21+
log.info(msg)
22+
23+
class ExampleDistrib:
24+
25+
ID = "Example"
26+
NAME = "Example Distrib"
27+
28+
def __init__(self, releases):
29+
self.releases = releases
30+
31+
def getPackageName(self, update_id):
32+
pass
33+
34+
def getSpecfileContent(self, pkgName, releaseTag):
35+
"""Implement this fct only if you want to use actions.WriteSpecfile()"""
36+
pass
37+
38+
def makeChroot(self, distRelease):
39+
pass

Diff for: p2-update-checker/src/distFedora.py

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import fedora.client.pkgdb
2+
import fedora.client.fas2
3+
import entity
4+
import logging
5+
import os
6+
import tempfile
7+
import utils
8+
import commands
9+
import config
10+
11+
FAS_USER = "alcapcom"
12+
FAS_PWD = "fiscodan_xl"
13+
14+
class Distrib:
15+
16+
ID = "fedora"
17+
NAME = "Fedora Project"
18+
19+
def __init__(self, releases):
20+
self.releases = releases
21+
22+
def getPackageName(self, updateId):
23+
cmd = "rpm -q --whatprovides --qf '%{NAME} ' " + "osgi\(%s\)" % updateId
24+
s, o = commands.getstatusoutput(cmd)
25+
# FIXME: here we take the first package that provide the given osgi bundle.
26+
o.split(' ')[0]
27+
return s, o
28+
29+
def getSpecfileContent(self, pkgName, tag):
30+
pwd = commands.getoutput("pwd");
31+
tmpDir = tempfile.mkdtemp("%s-%s_spec" % (config.APP_NAME, pkgName))
32+
os.chdir(tmpDir)
33+
specfile = os.path.join(pkgName, tag, pkgName + ".spec")
34+
cmd = "CVSROOT=:pserver:[email protected]:/cvs/pkgs cvs co %s" % specfile
35+
status = os.system(cmd)
36+
if status > 0:
37+
config.LOG.error("Error during '%s'" % cmd)
38+
return
39+
content = utils.readFile(specfile)
40+
os.chdir(pwd)
41+
os.system("rm -rf " + tmpDir)
42+
return content
43+
44+
def makeChroot(self, distRelease):
45+
outputDir = os.path.join(config.OUTPUT_DIR, "mock", distRelease.tag)
46+
if os.path.exists(config.CHROOT_DIR % distRelease.mockConfig):
47+
cmd = "mock --update -r %s --resultdir=%s" % (distRelease.mockConfig, outputDir)
48+
else:
49+
cmd = "mock --init -r %s --resultdir=%s" % (distRelease.mockConfig, outputDir)
50+
status = os.system(cmd)
51+
if status > 0:
52+
config.LOG.error("Error during '%s'" % cmd)
53+
return
54+
cmd = "mock --install -r %s eclipse\* --resultdir=%s" % (distRelease.mockConfig, outputDir)
55+
status = os.system(cmd)
56+
if status > 0:
57+
config.LOG.error("Error during '%s'" % cmd)
58+
return
59+
return
60+
61+
# TODO: add co-maintainers
62+
class Process:
63+
64+
DESCRIPTION = "Fedora Process"
65+
66+
def run(self, pkgsToUpdate, distRelease):
67+
pkgdb = fedora.client.pkgdb.PackageDB()
68+
for pkgToUpdate in pkgsToUpdate:
69+
pkgName = pkgToUpdate.packageName.strip()
70+
if distRelease.tag == "devel":
71+
tag = "F-devel"
72+
else:
73+
tag = distRelease.tag
74+
pkg_info = pkgdb.get_package_info(pkgName, tag)
75+
pkg_info = pkg_info['packageListings'][0]
76+
owner = pkg_info['owneruser']
77+
78+
fas = fedora.client.fas2.AccountSystem()
79+
fas.username = FAS_USER
80+
fas.password = FAS_PWD
81+
person = fas.person_by_username(owner)
82+
83+
packager = entity.Packager(owner, person["human_name"] , person["email"], config.DISTRIB, pkgName)
84+
for action in config.ACTIONS:
85+
actionOutput = action.run(pkgToUpdate, packager, distRelease)
86+
loginfo = "%s (%s) for %s [%s]" % (action.DESCRIPTION, pkgToUpdate.packageName, packager.name, actionOutput)
87+
config.LOG.info(loginfo)

0 commit comments

Comments
 (0)