diff --git a/hgext/fix.py b/hgext/fix.py --- a/hgext/fix.py +++ b/hgext/fix.py @@ -214,6 +214,13 @@ _(b'REV'), ) revopt = (b'r', b'rev', [], _(b'revisions to fix'), _(b'REV')) +sourceopt = ( + b's', + b'source', + [], + _(b'fix the specified revisions and their descendants'), + _(b'REV'), +) wdiropt = (b'w', b'working-dir', False, _(b'fix the working directory')) wholeopt = (b'', b'whole', False, _(b'always fix every line of a file')) usage = _(b'[OPTION]... [FILE]...') @@ -221,7 +228,7 @@ @command( b'fix', - [allopt, baseopt, revopt, wdiropt, wholeopt], + [allopt, baseopt, revopt, sourceopt, wdiropt, wholeopt], usage, helpcategory=command.CATEGORY_FILE_CONTENTS, ) @@ -249,8 +256,10 @@ override this default behavior, though it is not usually desirable to do so. """ opts = pycompat.byteskwargs(opts) - cmdutil.check_at_most_one_arg(opts, b'all', b'rev') - cmdutil.check_incompatible_arguments(opts, b'working_dir', [b'all']) + cmdutil.check_at_most_one_arg(opts, b'all', b'source', b'rev') + cmdutil.check_incompatible_arguments( + opts, b'working_dir', [b'all', b'source'] + ) with repo.wlock(), repo.lock(), repo.transaction(b'fix'): revstofix = getrevstofix(ui, repo, opts) @@ -399,6 +408,14 @@ """Returns the set of revision numbers that should be fixed""" if opts[b'all']: revs = repo.revs(b'(not public() and not obsolete()) or wdir()') + elif opts[b'source']: + source_revs = scmutil.revrange(repo, opts[b'source']) + revs = set(repo.revs(b'%ld::', source_revs)) + if wdirrev in source_revs: + # `wdir()::` is currently empty, so manually add wdir + revs.add(wdirrev) + if repo[b'.'].rev() in revs: + revs.add(wdirrev) else: revs = set(scmutil.revrange(repo, opts[b'rev'])) if opts.get(b'working_dir'): diff --git a/tests/test-fix-topology.t b/tests/test-fix-topology.t --- a/tests/test-fix-topology.t +++ b/tests/test-fix-topology.t @@ -21,6 +21,7 @@ $ cat >> $HGRCPATH < [extensions] > fix = + > strip = > [fix] > uppercase-whole-file:command="$PYTHON" $UPPERCASEPY > uppercase-whole-file:pattern=set:** @@ -262,6 +263,111 @@ $ cd .. + +Test the --source option. We only do this with obsstore on to avoid duplicating +test code. We rely on the other tests to prove that obsolescence is not an +important factor here. + +#if obsstore-on + $ hg init source-arg + $ cd source-arg + $ printf "aaaa\n" > a + $ hg commit -Am "change A" + adding a + $ printf "bbbb\n" > b + $ hg commit -Am "change B" + adding b + $ printf "cccc\n" > c + $ hg commit -Am "change C" + adding c + $ hg checkout 0 + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ printf "dddd\n" > d + $ hg commit -Am "change D" + adding d + created new head + $ hg log --graph --template '{rev} {desc}\n' + @ 3 change D + | + | o 2 change C + | | + | o 1 change B + |/ + o 0 change A + + +Test passing 'wdir()' to --source + $ printf "xxxx\n" > x + $ hg add x + $ hg fix -s 'wdir()' + $ cat * + aaaa + dddd + XXXX + +Test passing '.' to --source + $ printf "xxxx\n" > x + $ hg fix -s . + $ hg log --graph --template '{rev} {desc}\n' + @ 4 change D + | + | o 2 change C + | | + | o 1 change B + |/ + o 0 change A + + $ cat * + aaaa + DDDD + XXXX + $ hg strip -qf 4 + $ hg co -q 3 + +Test passing other branch to --source + $ printf "xxxx\n" > x + $ hg add x + $ hg fix -s 2 + $ hg log --graph --template '{rev} {desc}\n' + o 4 change C + | + | @ 3 change D + | | + o | 1 change B + |/ + o 0 change A + + $ hg cat -r 4 b c + bbbb + CCCC + $ cat * + aaaa + dddd + xxxx + $ hg strip -qf 4 + +Test passing multiple revisions to --source + $ hg fix -s '2 + .' + $ hg log --graph --template '{rev} {desc}\n' + @ 5 change D + | + | o 4 change C + | | + | o 1 change B + |/ + o 0 change A + + $ hg cat -r 4 b c + bbbb + CCCC + $ cat * + aaaa + DDDD + XXXX + + $ cd .. +#endif + The --all flag should fix anything that wouldn't cause a problem if you fixed it, including the working copy. Obsolete revisions are not fixed because that could cause divergence. Public revisions would cause an abort because they are diff --git a/tests/test-fix.t b/tests/test-fix.t --- a/tests/test-fix.t +++ b/tests/test-fix.t @@ -104,12 +104,13 @@ options ([+] can be repeated): - --all fix all non-public non-obsolete revisions - --base REV [+] revisions to diff against (overrides automatic selection, - and applies to every revision being fixed) - -r --rev REV [+] revisions to fix - -w --working-dir fix the working directory - --whole always fix every line of a file + --all fix all non-public non-obsolete revisions + --base REV [+] revisions to diff against (overrides automatic selection, + and applies to every revision being fixed) + -r --rev REV [+] revisions to fix + -s --source REV [+] fix the specified revisions and their descendants + -w --working-dir fix the working directory + --whole always fix every line of a file (some details hidden, use --verbose to show complete help)