def format_commit_lines(web_url, repo, base, tip): # type: (str, repo, int, int) -> str """ Format the per-commit information for the message, including the one-line commit summary and a link to the diff if a web URL has been configured: """ if web_url: rev_base_url = web_url.rstrip("/") + "/rev/" commit_summaries = [] for rev in range(base, tip): rev_node = repo.changelog.node(rev) rev_ctx = repo.changectx(rev_node) one_liner = rev_ctx.description().split("\n")[0] if web_url: summary_url = rev_base_url + str(rev_ctx) summary = "* [{summary}]({url})".format(summary=one_liner, url=summary_url) else: summary = "* {summary}".format(summary=one_liner) commit_summaries.append(summary) return "\n".join(summary for summary in commit_summaries)
def format_commit_lines(web_url, repo, base, tip): # type: (str, repo, int, int) -> str """ Format the per-commit information for the message, including the one-line commit summary and a link to the diff if a web URL has been configured: """ if web_url: rev_base_url = web_url.rstrip("/") + "/rev/" commit_summaries = [] for rev in range(base, tip): rev_node = repo.changelog.node(rev) rev_ctx = repo.changectx(rev_node) one_liner = rev_ctx.description().split("\n")[0] if web_url: summary_url = rev_base_url + str(rev_ctx) summary = "* [{summary}]({url})".format( summary=one_liner, url=summary_url) else: summary = "* {summary}".format(summary=one_liner) commit_summaries.append(summary) return "\n".join(summary for summary in commit_summaries)
def get_filechanges(repo,revision,parents,mleft): """Given some repository and revision, find all changed/deleted files.""" l,c,r=[],[],[] for p in parents: if p<0: continue mright=repo.changectx(p).manifest() l,c,r=split_dict(mleft,mright,l,c,r) l.sort() c.sort() r.sort() return l,c,r
def get_filechanges(repo,revision,parents,mleft): """Given some repository and revision, find all changed/deleted files.""" l,c,r=[],[],[] for p in parents: if p<0: continue mright=repo.changectx(p).manifest() dleft=mleft.keys() dleft.sort() dright=mright.keys() dright.sort() l,c,r=outer_set(mleft,mright,l,c,r) return l,c,r
def get_filechanges(repo, revision, parents, mleft): """Given some repository and revision, find all changed/deleted files.""" l, c, r = [], [], [] for p in parents: if p < 0: continue mright = repo.changectx(p).manifest() dleft = mleft.keys() dleft.sort() dright = mright.keys() dright.sort() l, c, r = outer_set(mleft, mright, l, c, r) return l, c, r
def get_property_pages(self, vfs_files): if len(vfs_files) != 1: return file = vfs_files[0] path = self.get_path_for_vfs_file(file) if path is None or file.is_directory(): return repo = self.get_repo_for_path(path) if repo is None: return localpath = path[len(repo.root) + 1 :] emblem, status = self._get_file_status(repo, localpath) # Get the information from Mercurial ctx = repo.workingctx().parents()[0] try: fctx = ctx.filectx(localpath) rev = fctx.filelog().linkrev(fctx.filenode()) except: rev = ctx.rev() ctx = repo.changectx(rev) node = short(ctx.node()) date = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(ctx.date()[0])) parents = "\n".join([short(p.node()) for p in ctx.parents()]) description = ctx.description() user = ctx.user() user = gobject.markup_escape_text(user) tags = ", ".join(ctx.tags()) branch = ctx.branch() self.property_label = gtk.Label("Mercurial") table = gtk.Table(7, 2, False) table.set_border_width(5) table.set_row_spacings(5) table.set_col_spacings(5) self.__add_row(table, 0, "<b>Status</b>:", status) self.__add_row(table, 1, "<b>Last-Commit-Revision</b>:", str(rev)) self.__add_row(table, 2, "<b>Last-Commit-Description</b>:", description) self.__add_row(table, 3, "<b>Last-Commit-Date</b>:", date) self.__add_row(table, 4, "<b>Last-Commit-User</b>:", user) if tags: self.__add_row(table, 5, "<b>Tags</b>:", tags) if branch != "default": self.__add_row(table, 6, "<b>Branch</b>:", branch) table.show() return (nautilus.PropertyPage("MercurialPropertyPage::status", self.property_label, table),)
def export_commit(ui,repo,revision,old_marks,max,count,authors,sob,brmap): def get_branchname(name): if brmap.has_key(name): return brmap[name] n=sanitize_name(name) brmap[name]=n return n (revnode,_,user,(time,timezone),files,desc,branch,_)=get_changeset(ui,repo,revision,authors) branch=get_branchname(branch) parents = [p for p in repo.changelog.parentrevs(revision) if p >= 0] if len(parents)==0 and revision != 0: wr('reset refs/heads/%s' % branch) wr('commit refs/heads/%s' % branch) wr('mark :%d' % (revision+1)) if sob: wr('author %s %d %s' % (get_author(desc,user,authors),time,timezone)) wr('committer %s %d %s' % (user,time,timezone)) wr('data %d' % (len(desc)+1)) # wtf? wr(desc) wr() # Sort the parents based on revision ids so that we always get the # same resulting git repo, no matter how the revisions were # numbered. parents.sort(key=repo.changelog.node, reverse=True) ctx=repo.changectx(str(revision)) man=ctx.manifest() added,changed,removed,type=[],[],[],'' if len(parents) == 0: # first revision: feed in full manifest added=man.keys() added.sort() type='full' else: wr('from %s' % revnum_to_revref(parents[0], old_marks)) if len(parents) == 1: # later non-merge revision: feed in changed manifest # if we have exactly one parent, just take the changes from the # manifest without expensively comparing checksums f=repo.status(repo.lookup(parents[0]),revnode)[:3] added,changed,removed=f[1],f[0],f[2] type='simple delta' else: # a merge with two parents wr('merge %s' % revnum_to_revref(parents[1], old_marks)) # later merge revision: feed in changed manifest # for many files comparing checksums is expensive so only do it for # merges where we really need it due to hg's revlog logic added,changed,removed=get_filechanges(repo,revision,parents,man) type='thorough delta' sys.stderr.write('%s: Exporting %s revision %d/%d with %d/%d/%d added/changed/removed files\n' % (branch,type,revision+1,max,len(added),len(changed),len(removed))) map(lambda r: wr('D %s' % r),removed) export_file_contents(ctx,man,added) export_file_contents(ctx,man,changed) wr() return checkpoint(count)
def hook(ui, repo, **kwargs): # type: (ui, repo, **Text) -> None """ Invoked by configuring a [hook] entry in .hg/hgrc. """ hooktype = kwargs["hooktype"] node = kwargs["node"] ui.debug("Zulip: received {hooktype} event\n".format(hooktype=hooktype)) if hooktype != "changegroup": ui.warn("Zulip: {hooktype} not supported\n".format(hooktype=hooktype)) sys.exit(1) ctx = repo.changectx(node) branch = ctx.branch() # If `branches` isn't specified, notify on all branches. branch_whitelist = get_config(ui, "branches") branch_blacklist = get_config(ui, "ignore_branches") if branch_whitelist: # Only send notifications on branches we are watching. watched_branches = [ b.lower().strip() for b in branch_whitelist.split(",") ] if branch.lower() not in watched_branches: ui.debug( "Zulip: ignoring event for {branch}\n".format(branch=branch)) sys.exit(0) if branch_blacklist: # Don't send notifications for branches we've ignored. ignored_branches = [ b.lower().strip() for b in branch_blacklist.split(",") ] if branch.lower() in ignored_branches: ui.debug( "Zulip: ignoring event for {branch}\n".format(branch=branch)) sys.exit(0) # The first and final commits in the changeset. base = repo[node].rev() tip = len(repo) email = get_config(ui, "email") api_key = get_config(ui, "api_key") site = get_config(ui, "site") if not (email and api_key): ui.warn("Zulip: missing email or api_key configurations\n") ui.warn("in the [zulip] section of your .hg/hgrc.\n") sys.exit(1) stream = get_config(ui, "stream") # Give a default stream if one isn't provided. if not stream: stream = "commits" web_url = get_config(ui, "web_url") user = ctx.user() content = format_summary_line(web_url, user, base, tip, branch, node) content += format_commit_lines(web_url, repo, base, tip) subject = branch ui.debug("Sending to Zulip:\n") ui.debug(content + "\n") send_zulip(email, api_key, site, stream, subject, content)
def export_commit(ui,repo,revision,marks,mapping,heads,last,max,count,authors,sob,brmap): def get_branchname(name): if brmap.has_key(name): return brmap[name] n=sanitize_name(name) brmap[name]=n return n (revnode,_,user,(time,timezone),files,desc,branch,_)=get_changeset(ui,repo,revision,authors) parents=repo.changelog.parentrevs(revision) branch=get_branchname(branch) wr('commit refs/heads/%s' % branch) wr('mark :%d' % (revision+1)) if sob: wr('author %s %d %s' % (get_author(desc,user,authors),time,timezone)) wr('committer %s %d %s' % (user,time,timezone)) wr('data %d' % (len(desc)+1)) # wtf? wr(desc) wr() pidx1, pidx2 = 0, 1 if parents[0] < parents[1]: pidx1, pidx2 = 1, 0 src=heads.get(branch,'') link='' if src!='': # if we have a cached head, this is an incremental import: initialize it # and kill reference so we won't init it again wr('from %s' % src) heads[branch]='' sys.stderr.write('%s: Initializing to parent [%s]\n' % (branch,src)) link=src # avoid making a merge commit for incremental import elif link=='' and not heads.has_key(branch) and revision>0: # newly created branch and not the first one: connect to parent tmp=get_parent_mark(parents[0],marks) wr('from %s' % tmp) sys.stderr.write('%s: Link new branch to parent [%s]\n' % (branch,tmp)) link=tmp # avoid making a merge commit for branch fork elif last.get(branch,revision) != parents[pidx1] and parents[pidx1] > 0 and revision > 0: pm=get_parent_mark(parents[pidx1],marks) sys.stderr.write('%s: Placing commit [r%d] in branch [%s] on top of [r%d]\n' % (branch,revision,branch,parents[pidx1])); wr('from %s' % pm) if parents[pidx2] > 0: pm=get_parent_mark(parents[pidx2],marks) sys.stderr.write('%s: Merging with parent [%s] from [r%d]\n' % (branch,pm,parents[pidx2])) wr('merge %s' % pm) last[branch]=revision heads[branch]='' # we need this later to write out tags marks[str(revision)]=':%d'%(revision+1) ctx=repo.changectx(str(revision)) man=ctx.manifest() added,changed,removed,type=[],[],[],'' if revision==0: # first revision: feed in full manifest added=man.keys() added.sort() type='full' elif is_merge(parents): # later merge revision: feed in changed manifest # for many files comparing checksums is expensive so only do it for # merges where we really need it due to hg's revlog logic added,changed,removed=get_filechanges(repo,revision,parents,man) type='thorough delta' else: # later non-merge revision: feed in changed manifest # if we have exactly one parent, just take the changes from the # manifest without expensively comparing checksums f=repo.status(repo.lookup(parents[0]),revnode)[:3] added,changed,removed=f[1],f[0],f[2] type='simple delta' sys.stderr.write('%s: Exporting %s revision %d/%d with %d/%d/%d added/changed/removed files\n' % (branch,type,revision+1,max,len(added),len(changed),len(removed))) map(lambda r: wr('D %s' % r),removed) export_file_contents(ctx,man,added) export_file_contents(ctx,man,changed) wr() return checkpoint(count)
def export_commit(ui,repo,revision,marks,heads,last,max,count,authors,sob): (revnode,_,user,(time,timezone),files,desc,branch,_)=get_changeset(ui,repo,revision,authors) parents=repo.changelog.parentrevs(revision) wr('commit refs/heads/%s' % branch) wr('mark :%d' % (revision+1)) if sob: wr('author %s %d %s' % (get_author(desc,user,authors),time,timezone)) wr('committer %s %d %s' % (user,time,timezone)) wr('data %d' % (len(desc)+1)) # wtf? wr(desc) wr() src=heads.get(branch,'') link='' if src!='': # if we have a cached head, this is an incremental import: initialize it # and kill reference so we won't init it again wr('from %s' % src) heads[branch]='' sys.stderr.write('Initializing branch [%s] to parent [%s]\n' % (branch,src)) link=src # avoid making a merge commit for incremental import elif link=='' and not heads.has_key(branch) and revision>0: # newly created branch and not the first one: connect to parent tmp=get_parent_mark(parents[0],marks) wr('from %s' % tmp) sys.stderr.write('Link new branch [%s] to parent [%s]\n' % (branch,tmp)) link=tmp # avoid making a merge commit for branch fork if parents: l=last.get(branch,revision) for p in parents: # 1) as this commit implicitely is the child of the most recent # commit of this branch, ignore this parent # 2) ignore nonexistent parents # 3) merge otherwise if p==l or p==revision or p<0: continue tmp=get_parent_mark(p,marks) # if we fork off a branch, don't merge with our parent via 'merge' # as we have 'from' already above if tmp==link: continue sys.stderr.write('Merging branch [%s] with parent [%s] from [r%d]\n' % (branch,tmp,p)) wr('merge %s' % tmp) last[branch]=revision heads[branch]='' # we need this later to write out tags marks[str(revision)]=':%d'%(revision+1) ctx=repo.changectx(str(revision)) man=ctx.manifest() added,changed,removed,type=[],[],[],'' if revision==0: # first revision: feed in full manifest added=man.keys() type='full' elif is_merge(parents): # later merge revision: feed in changed manifest # for many files comparing checksums is expensive so only do it for # merges where we really need it due to hg's revlog logic added,changed,removed=get_filechanges(repo,revision,parents,man) type='thorough delta' else: # later non-merge revision: feed in changed manifest # if we have exactly one parent, just take the changes from the # manifest without expensively comparing checksums f=repo.status(repo.lookup(parents[0]),revnode)[:3] added,changed,removed=f[1],f[0],f[2] type='simple delta' sys.stderr.write('Exporting %s revision %d/%d with %d/%d/%d added/changed/removed files\n' % (type,revision+1,max,len(added),len(changed),len(removed))) map(lambda r: wr('D %s' % r),removed) export_file_contents(ctx,man,added+changed) wr() return checkpoint(count)
def hook(ui, repo, **kwargs): # type: (ui, repo, Optional[Text]) -> None """ Invoked by configuring a [hook] entry in .hg/hgrc. """ hooktype = kwargs["hooktype"] node = kwargs["node"] ui.debug("Zulip: received {hooktype} event\n".format(hooktype=hooktype)) if hooktype != "changegroup": ui.warn("Zulip: {hooktype} not supported\n".format(hooktype=hooktype)) exit(1) ctx = repo.changectx(node) branch = ctx.branch() # If `branches` isn't specified, notify on all branches. branch_whitelist = get_config(ui, "branches") branch_blacklist = get_config(ui, "ignore_branches") if branch_whitelist: # Only send notifications on branches we are watching. watched_branches = [b.lower().strip() for b in branch_whitelist.split(",")] if branch.lower() not in watched_branches: ui.debug("Zulip: ignoring event for {branch}\n".format(branch=branch)) exit(0) if branch_blacklist: # Don't send notifications for branches we've ignored. ignored_branches = [b.lower().strip() for b in branch_blacklist.split(",")] if branch.lower() in ignored_branches: ui.debug("Zulip: ignoring event for {branch}\n".format(branch=branch)) exit(0) # The first and final commits in the changeset. base = repo[node].rev() tip = len(repo) email = get_config(ui, "email") api_key = get_config(ui, "api_key") site = get_config(ui, "site") if not (email and api_key): ui.warn("Zulip: missing email or api_key configurations\n") ui.warn("in the [zulip] section of your .hg/hgrc.\n") exit(1) stream = get_config(ui, "stream") # Give a default stream if one isn't provided. if not stream: stream = "commits" web_url = get_config(ui, "web_url") user = ctx.user() content = format_summary_line(web_url, user, base, tip, branch, node) content += format_commit_lines(web_url, repo, base, tip) subject = branch ui.debug("Sending to Zulip:\n") ui.debug(content + "\n") send_zulip(email, api_key, site, stream, subject, content)
def export_commit(ui, repo, revision, marks, heads, last, max, count, authors, sob): (revnode, _, user, (time, timezone), files, desc, branch, _) = get_changeset(ui, repo, revision, authors) parents = repo.changelog.parentrevs(revision) wr('commit refs/heads/%s' % branch) wr('mark :%d' % (revision + 1)) if sob: wr('author %s %d %s' % (get_author(desc, user, authors), time, timezone)) wr('committer %s %d %s' % (user, time, timezone)) wr('data %d' % (len(desc) + 1)) # wtf? wr(desc) wr() src = heads.get(branch, '') link = '' if src != '': # if we have a cached head, this is an incremental import: initialize it # and kill reference so we won't init it again wr('from %s' % src) heads[branch] = '' sys.stderr.write('Initializing branch [%s] to parent [%s]\n' % (branch, src)) link = src # avoid making a merge commit for incremental import elif link == '' and not heads.has_key(branch) and revision > 0: # newly created branch and not the first one: connect to parent tmp = get_parent_mark(parents[0], marks) wr('from %s' % tmp) sys.stderr.write('Link new branch [%s] to parent [%s]\n' % (branch, tmp)) link = tmp # avoid making a merge commit for branch fork if parents: l = last.get(branch, revision) for p in parents: # 1) as this commit implicitely is the child of the most recent # commit of this branch, ignore this parent # 2) ignore nonexistent parents # 3) merge otherwise if p == l or p == revision or p < 0: continue tmp = get_parent_mark(p, marks) # if we fork off a branch, don't merge with our parent via 'merge' # as we have 'from' already above if tmp == link: continue sys.stderr.write( 'Merging branch [%s] with parent [%s] from [r%d]\n' % (branch, tmp, p)) wr('merge %s' % tmp) last[branch] = revision heads[branch] = '' # we need this later to write out tags marks[str(revision)] = ':%d' % (revision + 1) ctx = repo.changectx(str(revision)) man = ctx.manifest() added, changed, removed, type = [], [], [], '' if revision == 0: # first revision: feed in full manifest added = man.keys() type = 'full' elif is_merge(parents): # later merge revision: feed in changed manifest # for many files comparing checksums is expensive so only do it for # merges where we really need it due to hg's revlog logic added, changed, removed = get_filechanges(repo, revision, parents, man) type = 'thorough delta' else: # later non-merge revision: feed in changed manifest # if we have exactly one parent, just take the changes from the # manifest without expensively comparing checksums f = repo.status(repo.lookup(parents[0]), revnode)[:3] added, changed, removed = f[1], f[0], f[2] type = 'simple delta' sys.stderr.write( 'Exporting %s revision %d/%d with %d/%d/%d added/changed/removed files\n' % (type, revision + 1, max, len(added), len(changed), len(removed))) map(lambda r: wr('D %s' % r), removed) export_file_contents(ctx, man, added + changed) wr() return checkpoint(count)