diff options
author | Richard Lowe <richlowe@richlowe.net> | 2009-08-05 16:12:50 -0700 |
---|---|---|
committer | Richard Lowe <richlowe@richlowe.net> | 2009-08-05 16:12:50 -0700 |
commit | 0df7087fda4bb16f7e1cf07d1b90fcf070c19484 (patch) | |
tree | 184220de307cff74050f20dec20985ee38d647dc /usr/src/tools/onbld | |
parent | 2ab4ca4ba67b0dc870fbd57becdb9ea51d9b8663 (diff) | |
download | illumos-gate-0df7087fda4bb16f7e1cf07d1b90fcf070c19484.tar.gz |
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
Diffstat (limited to 'usr/src/tools/onbld')
-rw-r--r-- | usr/src/tools/onbld/Scm/WorkSpace.py | 147 | ||||
-rw-r--r-- | usr/src/tools/onbld/hgext/cdm.py | 129 |
2 files changed, 111 insertions, 165 deletions
diff --git a/usr/src/tools/onbld/Scm/WorkSpace.py b/usr/src/tools/onbld/Scm/WorkSpace.py index 37f7c3db35..814415dc1c 100644 --- a/usr/src/tools/onbld/Scm/WorkSpace.py +++ b/usr/src/tools/onbld/Scm/WorkSpace.py @@ -440,70 +440,64 @@ class WorkSpace(object): 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 - - def _localtip(self, bases, heads): - '''Return a tuple (changectx, workingctx) representing the most - representative head to act as the local tip. + '''Return the canonical workspace parent, either SPEC (which + will be expanded) if provided or the default parent + otherwise.''' - 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. + if spec: + return self.ui.expandpath(spec) - 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. + p = self.ui.expandpath('default') + if p == 'default': + return None + else: + return p - 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.''' + def _localtip(self, outgoing, wctx): + '''Return the most representative changeset to act as the + localtip. - def tipmost_of(nodes): - return sorted(nodes, cmp=lambda x, y: cmp(x.rev(), y.rev()))[-1] + If the working directory is modified (has file changes, is a + merge, or has switched branches), this will be a workingctx. - # - # 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() + 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. + ''' # - # 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] + + if len(heads) > 1: + self.ui.warn('The current branch has more than one head, ' + 'using %s\n' % ltip.rev()) - localchoices = [n for n in heads if n.node() in outnodes] - return (tipmost_of(localchoices or heads), wctx) + 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 @@ class WorkSpace(object): 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 @@ class WorkSpace(object): elif st == 'iter': if n in seen: return rev - return None - - tipctx, wctx = localtip - parent = self.parent(parent) - outgoing = None - - if parent: - outgoing = self.findoutgoing(parent) - - if wctx: - possible_branches = wctx.parents() - else: - possible_branches = [tipctx] + return self.repo.changelog.rev(node.nullid) - 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 @@ class WorkSpace(object): 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 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) + if localtip.rev() is None: + heads = localtip.parents() else: - ctxs = [self.repo.changectx(n) for n in - self.repo.changelog.nodesbetween(outgoing, - [ourhead.node()])[0]] + heads = [localtip] + + ctxs = [self.repo.changectx(n) for n in + self.repo.changelog.nodesbetween(outgoing, + [h.node() for h in heads])[0]] + + if localtip.rev() is None: + ctxs.append(localtip) - act = ActiveList(self, self._parenttip((ourhead, workinghead), parent), - ctxs) + act = ActiveList(self, self._parenttip(heads, outnodes), ctxs) self.activecache[parent] = act return act diff --git a/usr/src/tools/onbld/hgext/cdm.py b/usr/src/tools/onbld/hgext/cdm.py index aa1cd42f49..ef31854218 100644 --- a/usr/src/tools/onbld/hgext/cdm.py +++ b/usr/src/tools/onbld/hgext/cdm.py @@ -75,47 +75,22 @@ def yes_no(ui, msg, default): return False -def _buildfilelist(repo, args): - '''build a list of files in which we're interested +def buildfilelist(ws, parent, files): + '''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. + If no files are specified take files from the active list relative + to 'parent'. - 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.''' + 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.''' - fdict = {} - - # - # 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 - - # - # 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 @@ def cdm_cddlchk(ui, repo, *args, **opts): 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) - - ui.write('CDDL block check:\n') - + filelist = buildfilelist(wslist[repo], opts.get('parent'), args) + exclude = not_check(repo, 'cddlchk') lenient = True ret = 0 - exclude = not_check(repo, 'cddlchk') + ui.write('CDDL block check:\n') - 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 @@ def cdm_mapfilechk(ui, repo, *args, **opts): 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 @@ def cdm_copyright(ui, repo, *args, **opts): 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_copyright(ui, repo, *args, **opts): 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 @@ def cdm_cstyle(ui, repo, *args, **opts): 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_cstyle(ui, repo, *args, **opts): 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_jstyle(ui, repo, *args, **opts): 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_rtichk(ui, repo, **opts): 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 @@ def run_checks(ws, cmds, *args, **opts): 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 |