def _getRemoteRevision(url): """ Parses and returns the revision number from a remote SVN repository. The URL must be correctly escaped (+ for space, etc). A BugError exception is raised if the URL can't be connected to or it doesn't have the expected format. This function looks specifically for the string 'Revision: ####' anywhere in the first MAX_READ_LINES """ try: timer = BugUtil.Timer("SvnUtil.getRevision") try: BugUtil.debug("SvnUtil.getRevision - opening '%s'", url) web = urllib.urlopen(urllib.quote(url, "/:")) count = 0 try: for line in web: result = REVISION_PATTERN.search(line) if result: BugUtil.debug("SvnUtil.getRevision - found '%s'", result.group()) try: return int(result.group(1)) except ValueError: raise BugUtil.BugError("invalid SVN revision format '%s'" % result.group(1)) count += 1 if count > MAX_READ_LINES: return None finally: web.close() except IOError, e: raise BugUtil.BugError("failed to access SVN repository: %s" % str(e)) return None
def getLocalRevision(path): """ Parses and returns the revision number from a local SVN working copy. It is read from the 'entries' file as long as the file has format 7 or higher. A BugError exception is raised if the file isn't found or it has an incorrect format or revision number format. Based on http://svn.collab.net/repos/svn/trunk/tools/client-side/change-svn-wc-format.py See http://svn.collab.net/repos/svn/trunk/subversion/libsvn_wc/README 'The entries file' for a description of the entries file format. In summary, the first line is the format number followed by an entry for the directory itself (no name). Each entry is separated by a form feed 0x0c and a line feed 0x0a, and each entry contains lines terminated by 0x0a. Subsequent empty lines at the end of an entry may be omitted. The first few lines of each entry that we care about are - name empty for first entry (a.k.a. this_dir) - kind file or dir - revision 0 for entries not yet in repository - url - repository """ path = os.path.join(path, ".svn", "entries") try: BugUtil.debug("SvnUtil.getLocalRevision - opening '%s'", path) input = open(path, "r") try: # Read and discard WC format number from INPUT. Validate that it # is a supported format for conversion. format_line = input.readline().strip() BugUtil.debug("SvnUtil.getLocalRevision - format '%s'", format_line) try: format_nbr = int(format_line) except ValueError: raise BugUtil.BugError("invalid SVN entries file format '%s'" % format_line) if not format_nbr >= MINIMUM_ENTRIES_FORMAT: raise BugUtil.BugError("SVN entries file format %d too old" % format_nbr) # Verify first entry's name and kind. name = input.readline().strip() if name != "": BugUtil.warn("SvnUtil.getLocalRevision - first SVN entry has name '%s'", name) kind = input.readline().strip() if kind != "dir": BugUtil.warn("SvnUtil.getLocalRevision - first SVN is not a dir, kind '%s'", kind) # Extract the revision number for the first entry. rev_line = input.readline().strip() BugUtil.debug("SvnUtil.getLocalRevision - revision '%s'", rev_line) try: rev = int(rev_line) except ValueError: raise BugUtil.BugError("invalid SVN revision number format '%s'" % rev_line) return rev finally: input.close() except IOError, e: raise BugUtil.BugError("failed to read SVN entries file")