Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(656)

Unified Diff: third_party/buildbot_7_12/buildbot/changes/changes.py

Issue 12207158: Bye bye buildbot 0.7.12. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/buildbot_7_12/buildbot/changes/changes.py
diff --git a/third_party/buildbot_7_12/buildbot/changes/changes.py b/third_party/buildbot_7_12/buildbot/changes/changes.py
deleted file mode 100644
index 0be5e3029f423908faecb35eca6bcd1ca6471bae..0000000000000000000000000000000000000000
--- a/third_party/buildbot_7_12/buildbot/changes/changes.py
+++ /dev/null
@@ -1,360 +0,0 @@
-import sys, os, time
-from cPickle import dump
-
-from zope.interface import implements
-from twisted.python import log
-from twisted.internet import defer
-from twisted.application import service
-from twisted.web import html
-
-from buildbot import interfaces, util
-from buildbot.process.properties import Properties
-
-html_tmpl = """
-<p>Changed by: <b>%(who)s</b><br />
-Changed at: <b>%(at)s</b><br />
-%(repository)s
-%(branch)s
-%(revision)s
-<br />
-
-Changed files:
-%(files)s
-
-Comments:
-%(comments)s
-
-Properties:
-%(properties)s
-</p>
-"""
-
-class Change:
- """I represent a single change to the source tree. This may involve
- several files, but they are all changed by the same person, and there is
- a change comment for the group as a whole.
-
- If the version control system supports sequential repository- (or
- branch-) wide change numbers (like SVN, P4, and Arch), then revision=
- should be set to that number. The highest such number will be used at
- checkout time to get the correct set of files.
-
- If it does not (like CVS), when= should be set to the timestamp (seconds
- since epoch, as returned by time.time()) when the change was made. when=
- will be filled in for you (to the current time) if you omit it, which is
- suitable for ChangeSources which have no way of getting more accurate
- timestamps.
-
- Changes should be submitted to ChangeMaster.addChange() in
- chronologically increasing order. Out-of-order changes will probably
- cause the html.Waterfall display to be corrupted."""
-
- implements(interfaces.IStatusEvent)
-
- number = None
-
- branch = None
- category = None
- revision = None # used to create a source-stamp
- repository = None # optional repository
-
- def __init__(self, who, files, comments, isdir=0, links=None,
- revision=None, when=None, branch=None, category=None,
- repository='', revlink='', properties={}):
- self.who = who
- self.comments = comments
- self.isdir = isdir
- if links is None:
- links = []
- self.links = links
- self.revision = revision
- if when is None:
- when = util.now()
- self.when = when
- self.branch = branch
- self.category = category
- self.repository = repository
- self.revlink = revlink
- self.properties = Properties()
- self.properties.update(properties, "Change")
-
- # keep a sorted list of the files, for easier display
- self.files = files[:]
- self.files.sort()
-
- def __setstate__(self, dict):
- self.__dict__ = dict
- # Older Changes won't have a 'properties' attribute in them
- if not hasattr(self, 'properties'):
- self.properties = Properties()
-
- def asText(self):
- data = ""
- data += self.getFileContents()
- data += "At: %s\n" % self.getTime()
- data += "Changed By: %s\n" % self.who
- data += "Comments: %s" % self.comments
- data += "Properties: \n%s\n\n" % self.getProperties()
- return data
-
- def asHTML(self):
- links = []
- for file in self.files:
- link = filter(lambda s: s.find(file) != -1, self.links)
- if len(link) == 1:
- # could get confused
- links.append('<a href="%s"><b>%s</b></a>' % (link[0], file))
- else:
- links.append('<b>%s</b>' % file)
- if self.revision:
- if getattr(self, 'revlink', ""):
- revision = 'Revision: <a href="%s"><b>%s</b></a>\n' % (
- self.revlink, self.revision)
- else:
- revision = "Revision: <b>%s</b><br />\n" % self.revision
- else:
- revision = ''
-
- if self.repository:
- repository = "Repository: <b>%s</b><br />\n" % self.repository
- else:
- repository = ''
-
- branch = ""
- if self.branch:
- branch = "Branch: <b>%s</b><br />\n" % self.branch
-
- properties = []
- for prop in self.properties.asList():
- properties.append("%s: %s<br />" % (prop[0], prop[1]))
-
- kwargs = { 'who' : html.escape(self.who),
- 'at' : self.getTime(),
- 'files' : html.UL(links) + '\n',
- 'repository': repository,
- 'revision' : revision,
- 'branch' : branch,
- 'comments' : html.PRE(self.comments),
- 'properties': html.UL(properties) + '\n' }
- return html_tmpl % kwargs
-
- def get_HTML_box(self, url):
- """Return the contents of a TD cell for the waterfall display.
-
- @param url: the URL that points to an HTML page that will render
- using our asHTML method. The Change is free to use this or ignore it
- as it pleases.
-
- @return: the HTML that will be put inside the table cell. Typically
- this is just a single href named after the author of the change and
- pointing at the passed-in 'url'.
- """
- who = self.getShortAuthor()
- if self.comments is None:
- title = ""
- else:
- title = html.escape(self.comments)
- return '<a href="%s" title="%s">%s</a>' % (url,
- title,
- html.escape(who))
-
- def getShortAuthor(self):
- return self.who
-
- def getTime(self):
- if not self.when:
- return "?"
- return time.strftime("%a %d %b %Y %H:%M:%S",
- time.localtime(self.when))
-
- def getTimes(self):
- return (self.when, None)
-
- def getText(self):
- return [html.escape(self.who)]
- def getLogs(self):
- return {}
-
- def getFileContents(self):
- data = ""
- if len(self.files) == 1:
- if self.isdir:
- data += "Directory: %s\n" % self.files[0]
- else:
- data += "File: %s\n" % self.files[0]
- else:
- data += "Files:\n"
- for f in self.files:
- data += " %s\n" % f
- return data
-
- def getProperties(self):
- data = ""
- for prop in self.properties.asList():
- data += " %s: %s" % (prop[0], prop[1])
- return data
-
- def asDict(self):
- result = {}
- # Constant
- result['number'] = self.number
- result['branch'] = self.branch
- result['category'] = self.category
- result['who'] = self.getShortAuthor()
- result['comments'] = self.comments
- result['revision'] = self.revision
- result['repository'] = self.repository
- result['when'] = self.when
- result['files'] = self.files
- result['revlink'] = self.revlink
- result['properties'] = self.properties.asList()
- return result
-
-
-class ChangeMaster(service.MultiService):
-
- """This is the master-side service which receives file change
- notifications from CVS. It keeps a log of these changes, enough to
- provide for the HTML waterfall display, and to tell
- temporarily-disconnected bots what they missed while they were
- offline.
-
- Change notifications come from two different kinds of sources. The first
- is a PB service (servicename='changemaster', perspectivename='change'),
- which provides a remote method called 'addChange', which should be
- called with a dict that has keys 'filename' and 'comments'.
-
- The second is a list of objects derived from the ChangeSource class.
- These are added with .addSource(), which also sets the .changemaster
- attribute in the source to point at the ChangeMaster. When the
- application begins, these will be started with .start() . At shutdown
- time, they will be terminated with .stop() . They must be persistable.
- They are expected to call self.changemaster.addChange() with Change
- objects.
-
- There are several different variants of the second type of source:
-
- - L{buildbot.changes.mail.MaildirSource} watches a maildir for CVS
- commit mail. It uses DNotify if available, or polls every 10
- seconds if not. It parses incoming mail to determine what files
- were changed.
-
- - L{buildbot.changes.freshcvs.FreshCVSSource} makes a PB
- connection to the CVSToys 'freshcvs' daemon and relays any
- changes it announces.
-
- """
-
- implements(interfaces.IEventSource)
-
- debug = False
- # todo: use Maildir class to watch for changes arriving by mail
-
- changeHorizon = 0
-
- def __init__(self):
- service.MultiService.__init__(self)
- self.changes = []
- # self.basedir must be filled in by the parent
- self.nextNumber = 1
-
- def addSource(self, source):
- assert interfaces.IChangeSource.providedBy(source)
- assert service.IService.providedBy(source)
- if self.debug:
- print "ChangeMaster.addSource", source
- source.setServiceParent(self)
-
- def removeSource(self, source):
- assert source in self
- if self.debug:
- print "ChangeMaster.removeSource", source, source.parent
- d = defer.maybeDeferred(source.disownServiceParent)
- return d
-
- def addChange(self, change):
- """Deliver a file change event. The event should be a Change object.
- This method will timestamp the object as it is received."""
- log.msg("adding change, who %s, %d files, rev=%s, branch=%s, "
- "comments %s, category %s" % (change.who, len(change.files),
- change.revision, change.branch,
- change.comments, change.category))
- change.number = self.nextNumber
- self.nextNumber += 1
- self.changes.append(change)
- self.parent.addChange(change)
- self.pruneChanges()
-
- def pruneChanges(self):
- if self.changeHorizon and len(self.changes) > self.changeHorizon:
- log.msg("pruning %i changes" % (len(self.changes) - self.changeHorizon))
- self.changes = self.changes[-self.changeHorizon:]
-
- def eventGenerator(self, branches=[], categories=[], committers=[], minTime=0):
- for i in range(len(self.changes)-1, -1, -1):
- c = self.changes[i]
- if (c.when < minTime):
- break
- if (not branches or c.branch in branches) and (
- not categories or c.category in categories) and (
- not committers or c.who in committers):
- yield c
-
- def getChangeNumbered(self, num):
- if not self.changes:
- return None
- first = self.changes[0].number
- if first + len(self.changes)-1 != self.changes[-1].number:
- log.msg(self,
- "lost a change somewhere: [0] is %d, [%d] is %d" % \
- (self.changes[0].number,
- len(self.changes) - 1,
- self.changes[-1].number))
- for c in self.changes:
- log.msg("c[%d]: " % c.number, c)
- return None
- offset = num - first
- log.msg(self, "offset", offset)
- if 0 <= offset <= len(self.changes):
- return self.changes[offset]
- else:
- return None
-
- def __getstate__(self):
- d = service.MultiService.__getstate__(self)
- del d['parent']
- del d['services'] # lose all children
- del d['namedServices']
- return d
-
- def __setstate__(self, d):
- self.__dict__ = d
- # self.basedir must be set by the parent
- self.services = [] # they'll be repopulated by readConfig
- self.namedServices = {}
-
-
- def saveYourself(self):
- filename = os.path.join(self.basedir, "changes.pck")
- tmpfilename = filename + ".tmp"
- try:
- dump(self, open(tmpfilename, "wb"))
- if sys.platform == 'win32':
- # windows cannot rename a file on top of an existing one
- if os.path.exists(filename):
- os.unlink(filename)
- os.rename(tmpfilename, filename)
- except Exception, e:
- log.msg("unable to save changes")
- log.err()
-
- def stopService(self):
- self.saveYourself()
- return service.MultiService.stopService(self)
-
-class TestChangeMaster(ChangeMaster):
- """A ChangeMaster for use in tests that does not save itself"""
- def stopService(self):
- return service.MultiService.stopService(self)
-
-# vim: set ts=4 sts=4 sw=4 et:
« no previous file with comments | « third_party/buildbot_7_12/buildbot/changes/bonsaipoller.py ('k') | third_party/buildbot_7_12/buildbot/changes/dnotify.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698