Patchwork export: clobber files with -o (bc) (issue3652)

login
register
mail settings
Submitter Augie Fackler
Date Feb. 9, 2013, 9:42 p.m.
Message ID <1a2f4c633410f6bc49b9.1360446156@augie-macbookair>
Download mbox | patch
Permalink /patch/910/
State Accepted
Commit 1a2f4c633410f6bc49b94c65d74939165bbc2dd7
Headers show

Comments

Augie Fackler - Feb. 9, 2013, 9:42 p.m.
# HG changeset patch
# User Augie Fackler <raf@durin42.com>
# Date 1360445937 21600
# Node ID 1a2f4c633410f6bc49b94c65d74939165bbc2dd7
# Parent  0b6e6eacc939c303136cb38af108e307d640c26e
export: clobber files with -o (bc) (issue3652)

This violated user expectation. Updated the code to clobber files, but
preserve the behavior of appending multiple patches requested in a
single export. Includes tests.
Augie Fackler - Feb. 9, 2013, 10:16 p.m.
Kevin and Bryan generously looked this over in meatspace. Pushed.

On Feb 9, 2013, at 9:42 PM, Augie Fackler <raf@durin42.com> wrote:

> # HG changeset patch
> # User Augie Fackler <raf@durin42.com>
> # Date 1360445937 21600
> # Node ID 1a2f4c633410f6bc49b94c65d74939165bbc2dd7
> # Parent  0b6e6eacc939c303136cb38af108e307d640c26e
> export: clobber files with -o (bc) (issue3652)
> 
> This violated user expectation. Updated the code to clobber files, but
> preserve the behavior of appending multiple patches requested in a
> single export. Includes tests.
> 
> diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
> --- a/mercurial/cmdutil.py
> +++ b/mercurial/cmdutil.py
> @@ -170,7 +170,8 @@
>                          inst.args[0])
> 
> def makefileobj(repo, pat, node=None, desc=None, total=None,
> -                seqno=None, revwidth=None, mode='wb', pathname=None):
> +                seqno=None, revwidth=None, mode='wb', modemap={},
> +                pathname=None):
> 
>     writable = mode not in ('r', 'rb')
> 
> @@ -196,9 +197,11 @@
>         return pat
>     if util.safehasattr(pat, 'read') and 'r' in mode:
>         return pat
> -    return open(makefilename(repo, pat, node, desc, total, seqno, revwidth,
> -                              pathname),
> -                mode)
> +    fn = makefilename(repo, pat, node, desc, total, seqno, revwidth, pathname)
> +    mode = modemap.get(fn, mode)
> +    if mode == 'wb':
> +        modemap[fn] = 'ab'
> +    return open(fn, mode)
> 
> def openrevlog(repo, cmd, file_, opts):
>     """opens the changelog, manifest, a filelog or a given revlog"""
> @@ -539,6 +542,7 @@
> 
>     total = len(revs)
>     revwidth = max([len(str(rev)) for rev in revs])
> +    filemode = {}
> 
>     def single(rev, seqno, fp):
>         ctx = repo[rev]
> @@ -554,7 +558,8 @@
>             desc_lines = ctx.description().rstrip().split('\n')
>             desc = desc_lines[0]    #Commit always has a first line.
>             fp = makefileobj(repo, template, node, desc=desc, total=total,
> -                             seqno=seqno, revwidth=revwidth, mode='ab')
> +                             seqno=seqno, revwidth=revwidth, mode='wb',
> +                             modemap=filemode)
>             if fp != template:
>                 shouldclose = True
>         if fp and fp != sys.stdout and util.safehasattr(fp, 'name'):
> diff --git a/tests/test-export.t b/tests/test-export.t
> --- a/tests/test-export.t
> +++ b/tests/test-export.t
> @@ -91,13 +91,28 @@
>   foo-foo_10.patch
>   foo-foo_11.patch
> 
> +Doing it again clobbers the files rather than appending:
> +  $ hg export -v -o "foo-%m.patch" 2:3
> +  exporting patches:
> +  foo-foo_2.patch
> +  foo-foo_3.patch
> +  $ grep HG foo-foo_2.patch | wc -l
> +  \s*1 (re)
> +  $ grep HG foo-foo_3.patch | wc -l
> +  \s*1 (re)
> +
> Exporting 4 changesets to a file:
> 
>   $ hg export -o export_internal 1 2 3 4
>   $ grep HG export_internal | wc -l
>   \s*4 (re)
> 
> -Exporting 4 changesets to a file:
> +Doing it again clobbers the file rather than appending:
> +  $ hg export -o export_internal 1 2 3 4
> +  $ grep HG export_internal | wc -l
> +  \s*4 (re)
> +
> +Exporting 4 changesets to stdout:
> 
>   $ hg export 1 2 3 4 | grep HG | wc -l
>   \s*4 (re)
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel

Patch

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -170,7 +170,8 @@ 
                          inst.args[0])
 
 def makefileobj(repo, pat, node=None, desc=None, total=None,
-                seqno=None, revwidth=None, mode='wb', pathname=None):
+                seqno=None, revwidth=None, mode='wb', modemap={},
+                pathname=None):
 
     writable = mode not in ('r', 'rb')
 
@@ -196,9 +197,11 @@ 
         return pat
     if util.safehasattr(pat, 'read') and 'r' in mode:
         return pat
-    return open(makefilename(repo, pat, node, desc, total, seqno, revwidth,
-                              pathname),
-                mode)
+    fn = makefilename(repo, pat, node, desc, total, seqno, revwidth, pathname)
+    mode = modemap.get(fn, mode)
+    if mode == 'wb':
+        modemap[fn] = 'ab'
+    return open(fn, mode)
 
 def openrevlog(repo, cmd, file_, opts):
     """opens the changelog, manifest, a filelog or a given revlog"""
@@ -539,6 +542,7 @@ 
 
     total = len(revs)
     revwidth = max([len(str(rev)) for rev in revs])
+    filemode = {}
 
     def single(rev, seqno, fp):
         ctx = repo[rev]
@@ -554,7 +558,8 @@ 
             desc_lines = ctx.description().rstrip().split('\n')
             desc = desc_lines[0]    #Commit always has a first line.
             fp = makefileobj(repo, template, node, desc=desc, total=total,
-                             seqno=seqno, revwidth=revwidth, mode='ab')
+                             seqno=seqno, revwidth=revwidth, mode='wb',
+                             modemap=filemode)
             if fp != template:
                 shouldclose = True
         if fp and fp != sys.stdout and util.safehasattr(fp, 'name'):
diff --git a/tests/test-export.t b/tests/test-export.t
--- a/tests/test-export.t
+++ b/tests/test-export.t
@@ -91,13 +91,28 @@ 
   foo-foo_10.patch
   foo-foo_11.patch
 
+Doing it again clobbers the files rather than appending:
+  $ hg export -v -o "foo-%m.patch" 2:3
+  exporting patches:
+  foo-foo_2.patch
+  foo-foo_3.patch
+  $ grep HG foo-foo_2.patch | wc -l
+  \s*1 (re)
+  $ grep HG foo-foo_3.patch | wc -l
+  \s*1 (re)
+
 Exporting 4 changesets to a file:
 
   $ hg export -o export_internal 1 2 3 4
   $ grep HG export_internal | wc -l
   \s*4 (re)
 
-Exporting 4 changesets to a file:
+Doing it again clobbers the file rather than appending:
+  $ hg export -o export_internal 1 2 3 4
+  $ grep HG export_internal | wc -l
+  \s*4 (re)
+
+Exporting 4 changesets to stdout:
 
   $ hg export 1 2 3 4 | grep HG | wc -l
   \s*4 (re)