def _get_version_from_bzr_lib(path): import bzrlib.tag, bzrlib.branch fullpath = os.path.abspath(path) if sys.platform == 'win32': fullpath = fullpath.replace('\\', '/') fullpath = '/' + fullpath branch = bzrlib.branch.Branch.open('file://' + fullpath) tags = bzrlib.tag.BasicTags(branch) #print "Getting version information from bzr branch..." branch.lock_read() try: history = branch.iter_merge_sorted_revisions(direction="reverse") version = None extra_version = [] for revid, depth, revno, end_of_merge in history: for tag_name, tag_revid in tags.get_tag_dict().iteritems(): #print tag_revid, "<==>", revid if tag_revid == revid: #print "%s matches tag %s" % (revid, tag_name) version = [int(s) for s in tag_name.split('.')] ## if the current revision does not match the last ## tag, we append current revno to the version if tag_revid != branch.last_revision(): extra_version = [branch.revno()] break if version: break finally: branch.unlock() assert version is not None _version = version + extra_version return _version
def create_components_from_branches(branches=None): if branches is None: branches = os.listdir('/srv/lava/branches') components = {} for branch_name in branches: component = Component(branch_name) branch = bzrlib.branch.Branch.open( os.path.join('/srv/lava/branches', branch_name)) branch.lock_read() try: branch_tags = branch.tags.get_tag_dict() revno2release = {} release2revno = {} for tag, revid in branch_tags.iteritems(): if tag.startswith('release-'): try: revno = branch.revision_id_to_dotted_revno(revid) except bzrlib.errors.NoSuchRevision: pass else: if len(revno) > 1: continue revno2release[revno[0]] = tag[len('release-'):] release2revno[tag[len('release-'):]] = revno[0] if revno2release: component.released_revno = max(revno2release) component.last_release = revno2release[max(revno2release)] else: component.released_revno = None component.release2revno = release2revno component.revno2release = revno2release revno, revid = branch.last_revision_info() component.tip_revno = revno component.tip_revid = revid mainline_revs = [] unreleased_revs = [] while True: rev = branch.repository.get_revision(revid) if rev.message.strip() != 'post release bump': if component.released_revno and revno > component.released_revno: unreleased_revs.append((rev, revno)) mainline_revs.append((rev, revno)) if not rev.parent_ids: break revid = rev.parent_ids[0] revno -= 1 component.unreleased_revisions = unreleased_revs component.mainline_revs = mainline_revs finally: branch.unlock() components[branch_name] = component return components
def copy_tree(revid): files = files_cache[revid] = {} branch.lock_read() tree = branch.repository.revision_tree(revid) try: for path, entry in tree.iter_entries_by_dir(): files[path] = [entry.file_id, None] finally: branch.unlock() return files
def test_revision_history_when_locked(self): """Repeated calls to revision history will only call _gen_revision_history once while the branch is locked. """ branch, calls = self.get_instrumented_branch() # Lock the branch, then repeatedly call revision_history. branch.lock_read() try: branch.revision_history() branch.revision_history() self.assertEqual(['_gen_revision_history'], calls) finally: branch.unlock()
def test_cached_revision_history_not_accidentally_mutable(self): """When there's a cached version of the history, revision_history returns a copy of the cached data so that callers cannot accidentally corrupt the cache. """ branch = self.get_branch() # Lock the branch, then repeatedly call revision_history, mutating the # results. branch.lock_read() try: # The first time the data returned will not be in the cache. history = branch.revision_history() history.append('one') # The second time the data comes from the cache. history = branch.revision_history() history.append('two') # The revision_history() should still be unchanged, even though # we've mutated the return values from earlier calls. self.assertEqual([], branch.revision_history()) finally: branch.unlock()
def do_list(parser): master_branch = None for name in branches: if not master_branch: master_branch = name print "? refs/heads/%s" % name branch = get_remote_branch(master_branch) branch.lock_read() for tag, revid in branch.tags.get_tag_dict().items(): try: branch.revision_id_to_dotted_revno(revid) except bzrlib.errors.NoSuchRevision: continue if not ref_is_valid(tag): continue print "? refs/tags/%s" % tag tags[tag] = revid branch.unlock() print "@refs/heads/%s HEAD" % master_branch print
def export_branch(repo, name): ref = '%s/heads/%s' % (prefix, name) tip = marks.get_tip(name) branch = get_remote_branch(name) repo = branch.repository branch.lock_read() revs = branch.iter_merge_sorted_revisions(None, tip, 'exclude', 'forward') try: tip_revno = branch.revision_id_to_revno(tip) last_revno, _ = branch.last_revision_info() total = last_revno - tip_revno except bzrlib.errors.NoSuchRevision: tip_revno = 0 total = 0 for revid, _, seq, _ in revs: if marks.is_marked(revid): continue rev = repo.get_revision(revid) revno = seq[0] parents = rev.parent_ids time = rev.timestamp tz = rev.timezone committer = rev.committer.encode('utf-8') committer = "%s %u %s" % (fixup_user(committer), time, gittz(tz)) authors = rev.get_apparent_authors() if authors: author = authors[0].encode('utf-8') author = "%s %u %s" % (fixup_user(author), time, gittz(tz)) else: author = committer msg = rev.message.encode('utf-8') msg += '\n' if len(parents) == 0: parent = bzrlib.revision.NULL_REVISION else: parent = parents[0] cur_tree = repo.revision_tree(revid) prev = repo.revision_tree(parent) modified, removed = get_filechanges(cur_tree, prev) modified_final = export_files(cur_tree, modified) if len(parents) == 0: print 'reset %s' % ref print "commit %s" % ref print "mark :%d" % (marks.get_mark(revid)) print "author %s" % (author) print "committer %s" % (committer) print "data %d" % (len(msg)) print msg for i, p in enumerate(parents): try: m = rev_to_mark(p) except KeyError: # ghost? continue if i == 0: print "from :%s" % m else: print "merge :%s" % m for f in removed: print "D %s" % (f, ) for f in modified_final: print "M %s :%u %s" % f print if len(seq) > 1: # let's skip branch revisions from the progress report continue progress = (revno - tip_revno) if (progress % 100 == 0): if total: print "progress revision %d '%s' (%d/%d)" % (revno, name, progress, total) else: print "progress revision %d '%s' (%d)" % (revno, name, progress) branch.unlock() revid = branch.last_revision() # make sure the ref is updated print "reset %s" % ref print "from :%u" % rev_to_mark(revid) print marks.set_tip(name, revid)
def export_branch(repo, name): ref = '%s/heads/%s' % (prefix, name) tip = marks.get_tip(name) branch = get_remote_branch(name) repo = branch.repository branch.lock_read() revs = branch.iter_merge_sorted_revisions(None, tip, 'exclude', 'forward') try: tip_revno = branch.revision_id_to_revno(tip) last_revno, _ = branch.last_revision_info() total = last_revno - tip_revno except bzrlib.errors.NoSuchRevision: tip_revno = 0 total = 0 for revid, _, seq, _ in revs: if marks.is_marked(revid): continue rev = repo.get_revision(revid) revno = seq[0] parents = rev.parent_ids time = rev.timestamp tz = rev.timezone committer = rev.committer.encode('utf-8') committer = "%s %u %s" % (fixup_user(committer), time, gittz(tz)) authors = rev.get_apparent_authors() if authors: author = authors[0].encode('utf-8') author = "%s %u %s" % (fixup_user(author), time, gittz(tz)) else: author = committer msg = rev.message.encode('utf-8') msg += '\n' if len(parents) == 0: parent = bzrlib.revision.NULL_REVISION else: parent = parents[0] cur_tree = repo.revision_tree(revid) prev = repo.revision_tree(parent) modified, removed = get_filechanges(cur_tree, prev) modified_final = export_files(cur_tree, modified) if len(parents) == 0: print 'reset %s' % ref print "commit %s" % ref print "mark :%d" % (marks.get_mark(revid)) print "author %s" % (author) print "committer %s" % (committer) print "data %d" % (len(msg)) print msg for i, p in enumerate(parents): try: m = rev_to_mark(p) except KeyError: # ghost? continue if i == 0: print "from :%s" % m else: print "merge :%s" % m for f in removed: print "D %s" % (f,) for f in modified_final: print "M %s :%u %s" % f print if len(seq) > 1: # let's skip branch revisions from the progress report continue progress = (revno - tip_revno) if (progress % 100 == 0): if total: print "progress revision %d '%s' (%d/%d)" % (revno, name, progress, total) else: print "progress revision %d '%s' (%d)" % (revno, name, progress) branch.unlock() revid = branch.last_revision() # make sure the ref is updated print "reset %s" % ref print "from :%u" % rev_to_mark(revid) print marks.set_tip(name, revid)
def export_branch(repo, name): ref = '%s/heads/%s' % (prefix, name) tip = marks.get_tip(name) branch = get_remote_branch(name) repo = branch.repository branch.lock_read() revs = branch.iter_merge_sorted_revisions(None, tip, 'exclude', 'forward') try: tip_revno = branch.revision_id_to_revno(tip) last_revno, _ = branch.last_revision_info() total = last_revno - tip_revno except bzrlib.errors.NoSuchRevision: tip_revno = 0 total = 0 for revid, _, seq, _ in revs: if marks.is_marked(revid): continue rev = repo.get_revision(revid) revno = seq[0] parents = rev.parent_ids time = rev.timestamp tz = rev.timezone committer = rev.committer.encode('utf-8') committer = "%s %u %s" % (fixup_user(committer), time, gittz(tz)) authors = rev.get_apparent_authors() if authors: author = authors[0].encode('utf-8') author = "%s %u %s" % (fixup_user(author), time, gittz(tz)) else: author = committer msg = rev.message.encode('utf-8') msg += '\n' if rev.properties.has_key('file-info'): from bzrlib import bencode try: files = bencode.bdecode( rev.properties['file-info'].encode('utf-8')) except Exception, e: # protect against repository corruption # (happens in the wild, see MySQL tree) files = () rmsg = msg.rstrip('\r\n ') file_comments = [] for file in files: fmsg = file['message'].rstrip('\r\n ') # Skip empty file comments and file comments identical to the # commit comment (they originate from tools and policies that # require writing per-file comments and users simply copy-paste # revision comment over, these comments add no value as a part of # the commit comment). if fmsg == '' or fmsg == rmsg: continue file_comments.append(file['path'] + ':') for l in fmsg.split('\n'): file_comments.append(' ' + l) msg += '\n' + '\n'.join(file_comments) + '\n' if len(parents) == 0: parent = bzrlib.revision.NULL_REVISION else: parent = parents[0] cur_tree = repo.revision_tree(revid) prev = repo.revision_tree(parent) modified, removed = get_filechanges(cur_tree, prev) modified_final = export_files(cur_tree, modified) if len(parents) == 0: print 'reset %s' % ref print "commit %s" % ref print "mark :%d" % (marks.get_mark(revid)) print "author %s" % (author) print "committer %s" % (committer) print "data %d" % (len(msg)) print msg for i, p in enumerate(parents): try: m = rev_to_mark(p) except KeyError: # ghost? continue if i == 0: print "from :%s" % m else: print "merge :%s" % m for f in removed: print "D %s" % (f, ) for f in modified_final: print "M %s :%u %s" % f print if len(seq) > 1: # let's skip branch revisions from the progress report continue progress = (revno - tip_revno) if (progress % 100 == 0): if total: print "progress revision %d '%s' (%d/%d)" % (revno, name, progress, total) else: print "progress revision %d '%s' (%d)" % (revno, name, progress)
def export_branch(repo, name): ref = '%s/heads/%s' % (prefix, name) tip = marks.get_tip(name) branch = get_remote_branch(name) repo = branch.repository branch.lock_read() revs = branch.iter_merge_sorted_revisions(None, tip, 'exclude', 'forward') try: tip_revno = branch.revision_id_to_revno(tip) last_revno, _ = branch.last_revision_info() total = last_revno - tip_revno except bzrlib.errors.NoSuchRevision: tip_revno = 0 total = 0 for revid, _, seq, _ in revs: if marks.is_marked(revid): continue rev = repo.get_revision(revid) revno = seq[0] parents = rev.parent_ids time = rev.timestamp tz = rev.timezone committer = rev.committer.encode('utf-8') committer = "%s %u %s" % (fixup_user(committer), time, gittz(tz)) authors = rev.get_apparent_authors() if authors: author = authors[0].encode('utf-8') author = "%s %u %s" % (fixup_user(author), time, gittz(tz)) else: author = committer msg = rev.message.encode('utf-8') msg += '\n' if rev.properties.has_key('file-info'): from bzrlib import bencode try: files = bencode.bdecode(rev.properties['file-info'].encode('utf-8')) except Exception, e: # protect against repository corruption # (happens in the wild, see MySQL tree) files = () rmsg = msg.rstrip('\r\n ') file_comments = [] for file in files: fmsg = file['message'].rstrip('\r\n ') # Skip empty file comments and file comments identical to the # commit comment (they originate from tools and policies that # require writing per-file comments and users simply copy-paste # revision comment over, these comments add no value as a part of # the commit comment). if fmsg == '' or fmsg == rmsg: continue file_comments.append(file['path'] + ':') for l in fmsg.split('\n'): file_comments.append(' ' + l) msg += '\n' + '\n'.join(file_comments) + '\n' if len(parents) == 0: parent = bzrlib.revision.NULL_REVISION else: parent = parents[0] cur_tree = repo.revision_tree(revid) prev = repo.revision_tree(parent) modified, removed = get_filechanges(cur_tree, prev) modified_final = export_files(cur_tree, modified) if len(parents) == 0: print 'reset %s' % ref print "commit %s" % ref print "mark :%d" % (marks.get_mark(revid)) print "author %s" % (author) print "committer %s" % (committer) print "data %d" % (len(msg)) print msg for i, p in enumerate(parents): try: m = rev_to_mark(p) except KeyError: # ghost? continue if i == 0: print "from :%s" % m else: print "merge :%s" % m for f in removed: print "D %s" % (f,) for f in modified_final: print "M %s :%u %s" % f print if len(seq) > 1: # let's skip branch revisions from the progress report continue progress = (revno - tip_revno) if (progress % 100 == 0): if total: print "progress revision %d '%s' (%d/%d)" % (revno, name, progress, total) else: print "progress revision %d '%s' (%d)" % (revno, name, progress)
def make_html(components, instances): table = tags.table(class_='main') heading_row = tags.tr() for heading in 'component', 'tip revno', 'unreleased revisions', 'latest release': heading_row(tags.th(heading)) for instance_name in sorted(instances): heading_row(tags.th(instance_name, class_="instance-name")) table(tags.thead(heading_row)) tbody = tags.tbody() for name, component in sorted(components.items()): row = tags.tr(class_="component") revs_between_ids = {} extra_rows = [] def td(*args, **kwargs): row(tags.td(*args, **kwargs)) td(name) td(str(component.tip_revno), class_='version') unreleased_count = len(component.unreleased_revisions) if unreleased_count: id_ = get_id() td( tags.a(str(unreleased_count), href='#', class_='highlight'), class_='version clickable', id=id_) sub_name = 'revs between %s (r%s) and tip (r%s)' % ( component.last_release, component.released_revno, component.tip_revno) extra_rows.append( tags.tr( tags.td( format_revlist(component.unreleased_revisions, name=sub_name), colspan=str(4 + len(instances))), class_='hidden', id="show-" + id_)) elif not component.last_release: td(u'\N{EM DASH}', class_='version') else: td(str(unreleased_count), class_='version') if component.last_release: td(component.last_release, class_='version') else: td(u'???', class_='version') for instance_name, instance in sorted(instances.items()): ver, location = instance.get(name, (None, None)) if ver is None: td(u'\N{EM DASH}', class_='version') elif ver == component.last_release: td(ver, class_='version') elif ver in component.release2revno: revno_low = component.release2revno[ver] sub_name = 'revs between %s (r%s) and %s (r%s)' % ( ver, revno_low, component.last_release, component.released_revno) revlist = [] for rev, revno in component.mainline_revs: if revno_low < revno < component.released_revno: revlist.append((rev, revno)) if revlist: id_ = get_id() revs_between_ids[revno_low] = id_ extra_rows.append( tags.tr( tags.td( format_revlist(revlist, name=sub_name), colspan=str(4 + len(instances))), class_='hidden branch-diff', id="show-" + id_)) td( tags.a(ver, href='#', class_='highlight'), class_='version clickable', id=id_) else: td(tags.span(ver, class_='highlight'), class_='version') elif location: try: branch = bzrlib.branch.Branch.open(location) except bzrlib.errors.NoSuchBranch: td(tags.span(ver, class_='highlight'), class_='version') else: branch.lock_read() try: # This utterly half-assed version of bzr missing # doesn't take merges into account! revno, revid = branch.last_revision_info() ver = ver.split('dev')[0] + 'dev' + str(revno) mainline_revids = dict( (rev.revision_id, revno) for rev, revno in component.mainline_revs) in_branch_revs = [] while revid not in mainline_revids: rev = branch.repository.get_revision(revid) if rev.message != 'post release bump': in_branch_revs.append((rev, revno)) revno -= 1 if not rev.parent_ids: break revid = rev.parent_ids[0] tables = [] if in_branch_revs: tables.append( format_revlist( in_branch_revs, 'in branch (with nick %s) but not tip' % branch.nick)) in_trunk_revs = [] lca_revno = revno for rev, revno in component.mainline_revs: if revno > lca_revno: in_trunk_revs.append((rev, revno)) if in_trunk_revs: tables.append( format_revlist( in_trunk_revs, 'in tip but not branch')) if tables: id_ = get_id() td( tags.a(ver, href='#', class_='highlight'), class_='version clickable', id=id_) extra_rows.append( tags.tr( tags.td( tables, colspan=str(4 + len(instances))), class_='hidden branch-diff', id="show-" + id_)) else: if branch.last_revision() == component.tip_revno: td(ver, class_='highlight version') else: td(ver, class_='version') finally: branch.unlock() else: td(tags.span(ver, class_='highlight'), class_='version') tbody(row, *extra_rows) table(tbody) html = tags.html( tags.head( tags.title("Deployment report"), tags.script( src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js', type='text/javascript'), tags.script( src='https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js', type='text/javascript'), tags.script(CDATA(js), type='text/javascript'), tags.style(CDATA(css), type="text/css"), ), tags.body( tags.h1("Deployment report"), table, ), ) html(xmlns="http://www.w3.org/1999/xhtml") return DOCTYPE + flatten(html)
def make_html(components, instances): table = tags.table(class_='main') heading_row = tags.tr() for heading in 'component', 'tip revno', 'unreleased revisions', 'latest release': heading_row(tags.th(heading)) for instance_name in sorted(instances): heading_row(tags.th(instance_name, class_="instance-name")) table(tags.thead(heading_row)) tbody = tags.tbody() for name, component in sorted(components.items()): row = tags.tr(class_="component") revs_between_ids = {} extra_rows = [] def td(*args, **kwargs): row(tags.td(*args, **kwargs)) td(name) td(str(component.tip_revno), class_='version') unreleased_count = len(component.unreleased_revisions) if unreleased_count: id_ = get_id() td(tags.a(str(unreleased_count), href='#', class_='highlight'), class_='version clickable', id=id_) sub_name = 'revs between %s (r%s) and tip (r%s)' % ( component.last_release, component.released_revno, component.tip_revno) extra_rows.append( tags.tr(tags.td(format_revlist(component.unreleased_revisions, name=sub_name), colspan=str(4 + len(instances))), class_='hidden', id="show-" + id_)) elif not component.last_release: td(u'\N{EM DASH}', class_='version') else: td(str(unreleased_count), class_='version') if component.last_release: td(component.last_release, class_='version') else: td(u'???', class_='version') for instance_name, instance in sorted(instances.items()): ver, location = instance.get(name, (None, None)) if ver is None: td(u'\N{EM DASH}', class_='version') elif ver == component.last_release: td(ver, class_='version') elif ver in component.release2revno: revno_low = component.release2revno[ver] sub_name = 'revs between %s (r%s) and %s (r%s)' % ( ver, revno_low, component.last_release, component.released_revno) revlist = [] for rev, revno in component.mainline_revs: if revno_low < revno < component.released_revno: revlist.append((rev, revno)) if revlist: id_ = get_id() revs_between_ids[revno_low] = id_ extra_rows.append( tags.tr(tags.td(format_revlist(revlist, name=sub_name), colspan=str(4 + len(instances))), class_='hidden branch-diff', id="show-" + id_)) td(tags.a(ver, href='#', class_='highlight'), class_='version clickable', id=id_) else: td(tags.span(ver, class_='highlight'), class_='version') elif location: try: branch = bzrlib.branch.Branch.open(location) except bzrlib.errors.NoSuchBranch: td(tags.span(ver, class_='highlight'), class_='version') else: branch.lock_read() try: # This utterly half-assed version of bzr missing # doesn't take merges into account! revno, revid = branch.last_revision_info() ver = ver.split('dev')[0] + 'dev' + str(revno) mainline_revids = dict( (rev.revision_id, revno) for rev, revno in component.mainline_revs) in_branch_revs = [] while revid not in mainline_revids: rev = branch.repository.get_revision(revid) if rev.message != 'post release bump': in_branch_revs.append((rev, revno)) revno -= 1 if not rev.parent_ids: break revid = rev.parent_ids[0] tables = [] if in_branch_revs: tables.append( format_revlist( in_branch_revs, 'in branch (with nick %s) but not tip' % branch.nick)) in_trunk_revs = [] lca_revno = revno for rev, revno in component.mainline_revs: if revno > lca_revno: in_trunk_revs.append((rev, revno)) if in_trunk_revs: tables.append( format_revlist(in_trunk_revs, 'in tip but not branch')) if tables: id_ = get_id() td(tags.a(ver, href='#', class_='highlight'), class_='version clickable', id=id_) extra_rows.append( tags.tr(tags.td(tables, colspan=str(4 + len(instances))), class_='hidden branch-diff', id="show-" + id_)) else: if branch.last_revision() == component.tip_revno: td(ver, class_='highlight version') else: td(ver, class_='version') finally: branch.unlock() else: td(tags.span(ver, class_='highlight'), class_='version') tbody(row, *extra_rows) table(tbody) html = tags.html( tags.head( tags.title("Deployment report"), tags.script( src= 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js', type='text/javascript'), tags.script( src= 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js', type='text/javascript'), tags.script(CDATA(js), type='text/javascript'), tags.style(CDATA(css), type="text/css"), ), tags.body( tags.h1("Deployment report"), table, ), ) html(xmlns="http://www.w3.org/1999/xhtml") return DOCTYPE + flatten(html)