Mercurial > illumos > illumos-gate
changeset 10263:56e344f46306
6747190 Cadmium commands do not expand hgrc paths
6791858 Cadmium active list is incorrect if parent workspace contains no changesets
6831741 Many cadmium commands ignore -p/--parent
author | Richard Lowe <richlowe@richlowe.net> |
---|---|
date | Wed, 05 Aug 2009 16:12:50 -0700 |
parents | f0a682e100e9 |
children | 1196af6129ec |
files | usr/src/tools/onbld/Scm/WorkSpace.py usr/src/tools/onbld/hgext/cdm.py |
diffstat | 2 files changed, 112 insertions(+), 166 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/tools/onbld/Scm/WorkSpace.py Wed Aug 05 15:46:35 2009 -0700 +++ b/usr/src/tools/onbld/Scm/WorkSpace.py Wed Aug 05 16:12:50 2009 -0700 @@ -440,70 +440,64 @@ self.ui = self.repo.ui self.name = self.repo.root - parent = self.repo.ui.expandpath('default') - if parent == 'default': - parent = None - self.parentrepo = parent - self.activecache = {} self.outgoingcache = {} def parent(self, spec=None): - '''Return canonical workspace parent, either SPEC if passed, - or default parent otherwise''' - return spec or self.parentrepo + '''Return the canonical workspace parent, either SPEC (which + will be expanded) if provided or the default parent + otherwise.''' - def _localtip(self, bases, heads): - '''Return a tuple (changectx, workingctx) representing the most - representative head to act as the local tip. + if spec: + return self.ui.expandpath(spec) - If the working directory is modified, the changectx is its - tipmost local parent (or tipmost parent, if neither is - local), and the workingctx is non-null. + p = self.ui.expandpath('default') + if p == 'default': + return None + else: + return p - If the working directory is clean, the workingctx is null. - The changectx is the tip-most local head on the current branch. - If this can't be determined for some reason (e.g., the parent - repo is inacessible), changectx is the tip-most head on the - current branch. + def _localtip(self, outgoing, wctx): + '''Return the most representative changeset to act as the + localtip. - If the workingctx is non-null it is the actual local tip (and would - be the local tip in any generated ActiveList, for instance), - the better parent revision is returned also to aid callers needing - a real changeset to act as a surrogate for an uncommitted change.''' + If the working directory is modified (has file changes, is a + merge, or has switched branches), this will be a workingctx. - def tipmost_of(nodes): - return sorted(nodes, cmp=lambda x, y: cmp(x.rev(), y.rev()))[-1] + If the working directory is unmodified, this will be the most + recent (highest revision number) local (outgoing) head on the + current branch, if no heads are determined to be outgoing, it + will be the most recent head on the current branch. + ''' # - # We need a full set of outgoing nodes such that we can limit - # local branch heads to those which are outgoing - # - outnodes = self.repo.changelog.nodesbetween(bases, heads)[0] - wctx = self.workingctx() - - # - # A modified working context is seen as a proto-branch, where - # the 'heads' from our view are the parent revisions of that - # context. - # (and the working head is it) + # A modified working copy is seen as a proto-branch, and thus + # our only option as the local tip. # if (wctx.files() or len(wctx.parents()) > 1 or wctx.branch() != wctx.parents()[0].branch()): - heads = wctx.parents() - else: - heads = [self.repo.changectx(n) for n in heads] - wctx = None + return wctx + + heads = self.repo.heads(start=wctx.parents()[0].node()) + headctxs = [self.repo.changectx(n) for n in heads] + localctxs = [c for c in headctxs if c.node() in outgoing] + + ltip = sorted(localctxs or headctxs, key=lambda x: x.rev())[-1] - localchoices = [n for n in heads if n.node() in outnodes] - return (tipmost_of(localchoices or heads), wctx) + if len(heads) > 1: + self.ui.warn('The current branch has more than one head, ' + 'using %s\n' % ltip.rev()) + + return ltip - def _parenttip(self, localtip, parent=None): - '''Find the closest approximation of the parents tip, as best - as we can. + def _parenttip(self, heads, outgoing): + '''Return the highest-numbered, non-outgoing changeset that is + an ancestor of a changeset in heads. - In parent-less workspaces returns our tip (given the best - we can do is deal with uncommitted changes)''' + This is intended to find the most recent changeset on a given + branch that is shared between a parent and child workspace, + such that it can act as a stand-in for the parent workspace. + ''' def tipmost_shared(head, outnodes): '''Return the tipmost node on the same branch as head that is not @@ -514,15 +508,20 @@ and return the first node we see in the iter phase that was previously collected. + If no node is found (all revisions >= 0 are outgoing), the + only possible parenttip is the null node (node.nullid) + which is returned explicitly. + See the docstring of mercurial.cmdutil.walkchangerevs() for the phased approach to the iterator returned. The important part to note is that the 'add' phase gathers nodes, which the 'iter' phase then iterates through.''' + opts = {'rev': ['%s:0' % head.rev()], + 'follow': True} get = util.cachefunc(lambda r: self.repo.changectx(r).changeset()) changeiter = cmdutil.walkchangerevs(self.repo.ui, self.repo, [], - get, {'rev': ['%s:0' % head], - 'follow': True})[0] + get, opts)[0] seen = [] for st, rev, fns in changeiter: n = self.repo.changelog.node(rev) @@ -532,22 +531,10 @@ elif st == 'iter': if n in seen: return rev - return None - - tipctx, wctx = localtip - parent = self.parent(parent) - outgoing = None + return self.repo.changelog.rev(node.nullid) - if parent: - outgoing = self.findoutgoing(parent) - - if wctx: - possible_branches = wctx.parents() - else: - possible_branches = [tipctx] - - nodes = self.repo.changelog.nodesbetween(outgoing)[0] - ptips = map(lambda x: tipmost_shared(x.rev(), nodes), possible_branches) + nodes = set(outgoing) + ptips = map(lambda x: tipmost_shared(x, nodes), heads) return self.repo.changectx(sorted(ptips)[-1]) def status(self, base=None, head=None): @@ -614,30 +601,26 @@ if parent: outgoing = self.findoutgoing(parent) + outnodes = self.repo.changelog.nodesbetween(outgoing)[0] else: outgoing = [] # No parent, no outgoing nodes + outnodes = [] - branchheads = self.repo.heads(start=self.repo.dirstate.parents()[0]) - ourhead, workinghead = self._localtip(outgoing, branchheads) + localtip = self._localtip(outnodes, self.workingctx()) - if len(branchheads) > 1: - self.ui.warn('The current branch has more than one head, ' - 'using %s\n' % ourhead.rev()) + if localtip.rev() is None: + heads = localtip.parents() + else: + heads = [localtip] - if workinghead: - parents = workinghead.parents() - ctxs = [self.repo.changectx(n) for n in - self.repo.changelog.nodesbetween(outgoing, - [h.node() for h in - parents])[0]] - ctxs.append(workinghead) - else: - ctxs = [self.repo.changectx(n) for n in - self.repo.changelog.nodesbetween(outgoing, - [ourhead.node()])[0]] + ctxs = [self.repo.changectx(n) for n in + self.repo.changelog.nodesbetween(outgoing, + [h.node() for h in heads])[0]] - act = ActiveList(self, self._parenttip((ourhead, workinghead), parent), - ctxs) + if localtip.rev() is None: + ctxs.append(localtip) + + act = ActiveList(self, self._parenttip(heads, outnodes), ctxs) self.activecache[parent] = act return act
--- a/usr/src/tools/onbld/hgext/cdm.py Wed Aug 05 15:46:35 2009 -0700 +++ b/usr/src/tools/onbld/hgext/cdm.py Wed Aug 05 16:12:50 2009 -0700 @@ -75,47 +75,22 @@ return False -def _buildfilelist(repo, args): - '''build a list of files in which we're interested - - If no files are specified, then we'll default to using - the entire active list. +def buildfilelist(ws, parent, files): + '''Build a list of files in which we're interested. - Returns a dictionary, wherein the keys are cwd-relative file paths, - and the values (when present) are entries from the active list. - Instead of warning the user explicitly about files not in the active - list, we'll attempt to do checks on them.''' - - fdict = {} + If no files are specified take files from the active list relative + to 'parent'. - # - # If the user specified files on the command line, we'll only check - # those files. We won't pull the active list at all. That means we - # won't be smart about skipping deleted files and such, so the user - # needs to be smart enough to not explicitly specify a nonexistent - # file path. Which seems reasonable. - # - if args: - for f in args: - fdict[f] = None + Return a list of 2-tuples the first element being a path relative + to the current directory and the second an entry from the active + list, or None if an explicit file list was given.''' - # - # Otherwise, if no files were listed explicitly, we assume that the - # checks should be run on all files in the active list. So we determine - # it here. - # - # Tracking the file paths is a slight optimization, in that multiple - # check functions won't need to derive it themselves. This also dovetails - # nicely with the expectation that explicitly specified files will be - # ${CWD}-relative paths, so the fdict keyspace will be consistent either - # way. - # + if files: + return [(path, None) for path in sorted(files)] else: - active = wslist[repo].active() - for e in sorted(active): - fdict[wslist[repo].filepath(e.name)] = e - - return fdict + active = ws.active(parent=parent) + return [(ws.filepath(e.name), e) for e in sorted(active)] +buildfilelist = util.cachefunc(buildfilelist) def not_check(repo, cmd): @@ -303,16 +278,14 @@ See http://www.opensolaris.org/os/community/on/devref_toc/devref_7/#7_2_3_nonformatting_considerations for more info.''' - filelist = opts.get('filelist') or _buildfilelist(repo, args) + filelist = buildfilelist(wslist[repo], opts.get('parent'), args) + exclude = not_check(repo, 'cddlchk') + lenient = True + ret = 0 ui.write('CDDL block check:\n') - lenient = True - ret = 0 - - exclude = not_check(repo, 'cddlchk') - - for f, e in filelist.iteritems(): + for f, e in filelist: if e and e.is_removed(): continue elif (e or opts.get('honour_nots')) and exclude(f): @@ -336,14 +309,13 @@ header comment directing the reader to the document containing Solaris object versioning rules (README.mapfile).''' - filelist = opts.get('filelist') or _buildfilelist(repo, args) + filelist = buildfilelist(wslist[repo], opts.get('parent'), args) + exclude = not_check(repo, 'mapfilechk') + ret = 0 ui.write('Mapfile comment check:\n') - ret = 0 - exclude = not_check(repo, 'mapfilechk') - - for f, e in filelist.iteritems(): + for f, e in filelist: if e and e.is_removed(): continue elif f.find('mapfile') == -1: @@ -366,14 +338,13 @@ See http://www.opensolaris.org/os/project/muskoka/on_dev/golden_rules.txt for more info.''' - filelist = opts.get('filelist') or _buildfilelist(repo, args) + filelist = buildfilelist(wslist[repo], opts.get('parent'), args) + exclude = not_check(repo, 'copyright') + ret = 0 ui.write('Copyright check:\n') - ret = 0 - exclude = not_check(repo, 'copyright') - - for f, e in filelist.iteritems(): + for f, e in filelist: if e and e.is_removed(): continue elif (e or opts.get('honour_nots')) and exclude(f): @@ -389,14 +360,13 @@ def cdm_hdrchk(ui, repo, *args, **opts): '''check active header files conform to O/N rules''' - filelist = opts.get('filelist') or _buildfilelist(repo, args) + filelist = buildfilelist(wslist[repo], opts.get('parent'), args) + exclude = not_check(repo, 'hdrchk') + ret = 0 ui.write('Header format check:\n') - ret = 0 - exclude = not_check(repo, 'hdrchk') - - for f, e in filelist.iteritems(): + for f, e in filelist: if e and e.is_removed(): continue elif not f.endswith('.h'): @@ -416,14 +386,13 @@ See http://opensolaris.org/os/community/documentation/getting_started_docs/cstyle.ms.pdf''' - filelist = opts.get('filelist') or _buildfilelist(repo, args) + filelist = buildfilelist(wslist[repo], opts.get('parent'), args) + exclude = not_check(repo, 'cstyle') + ret = 0 ui.write('C style check:\n') - ret = 0 - exclude = not_check(repo, 'cstyle') - - for f, e in filelist.iteritems(): + for f, e in filelist: if e and e.is_removed(): continue elif not (f.endswith('.c') or f.endswith('.h')): @@ -443,14 +412,13 @@ def cdm_jstyle(ui, repo, *args, **opts): 'check active Java source files for common stylistic errors' - filelist = opts.get('filelist') or _buildfilelist(repo, args) + filelist = buildfilelist(wslist[repo], opts.get('parent'), args) + exclude = not_check(repo, 'jstyle') + ret = 0 ui.write('Java style check:\n') - ret = 0 - exclude = not_check(repo, 'jstyle') - - for f, e in filelist.iteritems(): + for f, e in filelist: if e and e.is_removed(): continue elif not f.endswith('.java'): @@ -468,14 +436,13 @@ def cdm_permchk(ui, repo, *args, **opts): '''check active files permission - warn +x (execute) mode''' - filelist = opts.get('filelist') or _buildfilelist(repo, args) + filelist = buildfilelist(wslist[repo], opts.get('parent'), args) + exclude = not_check(repo, 'permchk') + exeFiles = [] ui.write('File permission check:\n') - exeFiles = [] - exclude = not_check(repo, 'permchk') - - for f, e in filelist.iteritems(): + for f, e in filelist: if e and e.is_removed(): continue elif (e or opts.get('honour_nots')) and exclude(f): @@ -606,14 +573,13 @@ def cdm_keywords(ui, repo, *args, **opts): '''check source files do not contain SCCS keywords''' - filelist = opts.get('filelist') or _buildfilelist(repo, args) + filelist = buildfilelist(wslist[repo], opts.get('parent'), args) + exclude = not_check(repo, 'keywords') + ret = 0 ui.write('Keywords check:\n') - ret = 0 - exclude = not_check(repo, 'keywords') - - for f, e in filelist.iteritems(): + for f, e in filelist: if e and e.is_removed(): continue elif (e or opts.get('honour_nots')) and exclude(f): @@ -671,20 +637,17 @@ ret = 0 - flist = _buildfilelist(ws.repo, args) - for cmd in cmds: name = cmd.func_name.split('_')[1] if not ws.ui.configbool('cdm', name, True): ws.ui.status('Skipping %s check...\n' % name) else: ws.ui.pushbuffer() + result = cmd(ws.ui, ws.repo, honour_nots=True, *args, **opts) + output = ws.ui.popbuffer() - result = cmd(ws.ui, ws.repo, filelist=flist, - honour_nots=True, *args, **opts) ret |= result - output = ws.ui.popbuffer() if not ws.ui.quiet or result != 0: ws.ui.write(output, '\n') return ret