--- a/mercurial/commands.py Thu Dec 01 10:48:29 2005 -0600
+++ b/mercurial/commands.py Thu Dec 01 10:48:35 2005 -0600
@@ -821,16 +821,18 @@
ui.warn(_('%s: not overwriting - %s collides with %s\n') %
(reltarget, abssrc, prevsrc))
return
- elif os.path.exists(reltarget):
- if opts['force']:
- os.unlink(reltarget)
- else:
+ if (not opts['after'] and os.path.exists(reltarget) or
+ opts['after'] and repo.dirstate.state(abstarget) not in '?r'):
+ if not opts['force']:
ui.warn(_('%s: not overwriting - file exists\n') %
reltarget)
return
- if ui.verbose or not exact:
- ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
- if not opts['after']:
+ if not opts['after']:
+ os.unlink(reltarget)
+ if opts['after']:
+ if not os.path.exists(reltarget):
+ return
+ else:
targetdir = os.path.dirname(reltarget) or '.'
if not os.path.isdir(targetdir):
os.makedirs(targetdir)
@@ -847,10 +849,64 @@
(relsrc, inst.strerror))
errors += 1
return
+ if ui.verbose or not exact:
+ ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
targets[abstarget] = abssrc
repo.copy(abssrc, abstarget)
copied.append((abssrc, relsrc, exact))
+ def targetpathfn(pat, dest, srcs):
+ if os.path.isdir(pat):
+ if pat.endswith(os.sep):
+ pat = pat[:-len(os.sep)]
+ if destdirexists:
+ striplen = len(os.path.split(pat)[0])
+ else:
+ striplen = len(pat)
+ if striplen:
+ striplen += len(os.sep)
+ res = lambda p: os.path.join(dest, p[striplen:])
+ elif destdirexists:
+ res = lambda p: os.path.join(dest, os.path.basename(p))
+ else:
+ res = lambda p: dest
+ return res
+
+ def targetpathafterfn(pat, dest, srcs):
+ if util.patkind(pat, None)[0]:
+ # a mercurial pattern
+ res = lambda p: os.path.join(dest, os.path.basename(p))
+ elif len(util.canonpath(repo.root, cwd, pat)) < len(srcs[0][0]):
+ # A directory. Either the target path contains the last
+ # component of the source path or it does not.
+ def evalpath(striplen):
+ score = 0
+ for s in srcs:
+ t = os.path.join(dest, s[1][striplen:])
+ if os.path.exists(t):
+ score += 1
+ return score
+
+ if pat.endswith(os.sep):
+ pat = pat[:-len(os.sep)]
+ striplen = len(pat) + len(os.sep)
+ if os.path.isdir(os.path.join(dest, os.path.split(pat)[1])):
+ score = evalpath(striplen)
+ striplen1 = len(os.path.split(pat)[0])
+ if striplen1:
+ striplen1 += len(os.sep)
+ if evalpath(striplen1) > score:
+ striplen = striplen1
+ res = lambda p: os.path.join(dest, p[striplen:])
+ else:
+ # a file
+ if destdirexists:
+ res = lambda p: os.path.join(dest, os.path.basename(p))
+ else:
+ res = lambda p: dest
+ return res
+
+
pats = list(pats)
if not pats:
raise util.Abort(_('no source or destination specified'))
@@ -858,31 +914,31 @@
raise util.Abort(_('no destination specified'))
dest = pats.pop()
destdirexists = os.path.isdir(dest)
- if (len(pats) > 1 or not os.path.exists(pats[0])) and not destdirexists:
+ if (len(pats) > 1 or util.patkind(pats[0], None)[0]) and not destdirexists:
raise util.Abort(_('with multiple sources, destination must be an '
'existing directory'))
-
+ if opts['after']:
+ tfn = targetpathafterfn
+ else:
+ tfn = targetpathfn
+ copylist = []
for pat in pats:
- if os.path.isdir(pat):
- if destdirexists:
- striplen = len(os.path.split(pat)[0])
- else:
- striplen = len(pat)
- if striplen:
- striplen += len(os.sep)
- targetpath = lambda p: os.path.join(dest, p[striplen:])
- elif destdirexists:
- targetpath = lambda p: os.path.join(dest, os.path.basename(p))
- else:
- targetpath = lambda p: dest
+ srcs = []
for tag, abssrc, relsrc, exact in walk(repo, [pat], opts):
if okaytocopy(abssrc, relsrc, exact):
- copy(abssrc, relsrc, targetpath(abssrc), exact)
+ srcs.append((abssrc, relsrc, exact))
+ if not srcs:
+ continue
+ copylist.append((tfn(pat, dest, srcs), srcs))
+ if not copylist:
+ raise util.Abort(_('no files to copy'))
+
+ for targetpath, srcs in copylist:
+ for abssrc, relsrc, exact in srcs:
+ copy(abssrc, relsrc, targetpath(relsrc), exact)
if errors:
ui.warn(_('(consider using --after)\n'))
- if len(copied) == 0:
- raise util.Abort(_('no files to copy'))
return errors, copied
def copy(ui, repo, *pats, **opts):
--- a/tests/test-rename Thu Dec 01 10:48:29 2005 -0600
+++ b/tests/test-rename Thu Dec 01 10:48:35 2005 -0600
@@ -15,18 +15,56 @@
hg status
hg update -C
+echo "# rename --after a single file"
+mv d1/d11/a1 d2/c
+hg rename --after d1/d11/a1 d2/c
+hg status
+hg update -C
+
echo "# move a single file to an existing directory"
hg rename d1/d11/a1 d2
hg status
hg update -C
+echo "# move --after a single file to an existing directory"
+mv d1/d11/a1 d2
+hg rename --after d1/d11/a1 d2
+hg status
+hg update -C
+
+echo "# rename a file using a relative path"
+(cd d1/d11; hg rename ../../d2/b e)
+hg status
+hg update -C
+
+echo "# rename --after a file using a relative path"
+(cd d1/d11; mv ../../d2/b e; hg rename --after ../../d2/b e)
+hg status
+hg update -C
+
echo "# rename directory d1 as d3"
-hg rename d1 d3
+hg rename d1/ d3
+hg status
+hg update -C
+
+echo "# rename --after directory d1 as d3"
+mv d1 d3
+hg rename --after d1 d3
+hg status
+hg update -C
+
+echo "# move a directory using a relative path"
+(cd d2; mkdir d3; hg rename ../d1/d11 d3)
+hg status
+hg update -C
+
+echo "# move --after a directory using a relative path"
+(cd d2; mkdir d3; mv ../d1/d11 d3; hg rename --after ../d1/d11 d3)
hg status
hg update -C
echo "# move directory d1/d11 to an existing directory d2 (removes empty d1)"
-hg rename d1/d11 d2
+hg rename d1/d11/ d2
hg status
hg update -C
@@ -36,6 +74,13 @@
hg status
hg update -C
+echo "# move --after directories d1 and d2 to a new directory d3"
+mkdir d3
+mv d1 d2 d3
+hg rename --after d1 d2 d3
+hg status
+hg update -C
+
echo "# move everything under directory d1 to existing directory d2, do not"
echo "# overwrite existing files (d2/b)"
hg rename d1/* d2
@@ -53,6 +98,13 @@
hg status
hg update -C
+echo "# move --after some files under d1 to d2/d21 (glob)"
+mkdir d2/d21
+mv d1/a d1/d11/a1 d2/d21
+hg rename --after 'glob:d1/**' d2/d21
+hg status
+hg update -C
+
echo "# move every file under d1 starting with an 'a' to d2/d21 (regexp)"
mkdir d2/d21
hg rename 're:d1/([^a][^/]*/)*a.*' d2/d21
--- a/tests/test-rename.out Thu Dec 01 10:48:29 2005 -0600
+++ b/tests/test-rename.out Thu Dec 01 10:48:35 2005 -0600
@@ -1,9 +1,21 @@
# rename a single file
A d2/c
R d1/d11/a1
+# rename --after a single file
+A d2/c
+R d1/d11/a1
# move a single file to an existing directory
A d2/a1
R d1/d11/a1
+# move --after a single file to an existing directory
+A d2/a1
+R d1/d11/a1
+# rename a file using a relative path
+A d1/d11/e
+R d2/b
+# rename --after a file using a relative path
+A d1/d11/e
+R d2/b
# rename directory d1 as d3
copying d1/a to d3/a
copying d1/b to d3/b
@@ -21,6 +33,33 @@
R d1/b
R d1/ba
R d1/d11/a1
+# rename --after directory d1 as d3
+copying d1/a to d3/a
+copying d1/b to d3/b
+copying d1/ba to d3/ba
+copying d1/d11/a1 to d3/d11/a1
+removing d1/a
+removing d1/b
+removing d1/ba
+removing d1/d11/a1
+A d3/a
+A d3/b
+A d3/ba
+A d3/d11/a1
+R d1/a
+R d1/b
+R d1/ba
+R d1/d11/a1
+# move a directory using a relative path
+copying ../d1/d11/a1 to d3/d11/a1
+removing ../d1/d11/a1
+A d2/d3/d11/a1
+R d1/d11/a1
+# move --after a directory using a relative path
+copying ../d1/d11/a1 to d3/d11/a1
+removing ../d1/d11/a1
+A d2/d3/d11/a1
+R d1/d11/a1
# move directory d1/d11 to an existing directory d2 (removes empty d1)
copying d1/d11/a1 to d2/d11/a1
removing d1/d11/a1
@@ -47,6 +86,27 @@
R d1/ba
R d1/d11/a1
R d2/b
+# move --after directories d1 and d2 to a new directory d3
+copying d1/a to d3/d1/a
+copying d1/b to d3/d1/b
+copying d1/ba to d3/d1/ba
+copying d1/d11/a1 to d3/d1/d11/a1
+copying d2/b to d3/d2/b
+removing d1/a
+removing d1/b
+removing d1/ba
+removing d1/d11/a1
+removing d2/b
+A d3/d1/a
+A d3/d1/b
+A d3/d1/ba
+A d3/d1/d11/a1
+A d3/d2/b
+R d1/a
+R d1/b
+R d1/ba
+R d1/d11/a1
+R d2/b
# move everything under directory d1 to existing directory d2, do not
# overwrite existing files (d2/b)
d2/b: not overwriting - file exists
@@ -82,6 +142,15 @@
R d1/b
R d1/ba
R d1/d11/a1
+# move --after some files under d1 to d2/d21 (glob)
+copying d1/a to d2/d21/a
+copying d1/d11/a1 to d2/d21/a1
+removing d1/a
+removing d1/d11/a1
+A d2/d21/a
+A d2/d21/a1
+R d1/a
+R d1/d11/a1
# move every file under d1 starting with an 'a' to d2/d21 (regexp)
copying d1/a to d2/d21/a
copying d1/d11/a1 to d2/d21/a1
@@ -93,7 +162,6 @@
R d1/d11/a1
# attempt to overwrite an existing file
d1/ca: not overwriting - file exists
-abort: no files to copy
? d1/ca
# forced overwrite of an existing file
A d1/ca