changeset 363:ae96b7e1318d

Add hg copy -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Add hg copy extend dirstate to remember copies add copy command add copy repo operation write copy metadata with commit manifest hash: 9f42c7b4a2400d35807b5f18c05a31814fa3e375 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.0 (GNU/Linux) iD8DBQFCsMBTywK+sNU5EO8RAjXpAJ9fvNtTP1A/4veqFWQHcWGro7buyACgoVXz /ngGOFowxS/zGkvUvGavYGQ= =drb1 -----END PGP SIGNATURE-----
author mpm@selenic.com
date Wed, 15 Jun 2005 15:57:07 -0800
parents 410373162036
children 6f43778f26da
files mercurial/commands.py mercurial/hg.py tests/test-copy tests/test-copy.out
diffstat 4 files changed, 108 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/commands.py	Wed Jun 15 15:50:28 2005 -0800
+++ b/mercurial/commands.py	Wed Jun 15 15:57:07 2005 -0800
@@ -250,6 +250,10 @@
         addremove(ui, repo, *files)
     repo.commit(relpath(repo, files), text, opts['user'], opts['date'])
 
+def copy(ui, repo, source, dest):
+    """mark a file as copied or renamed for the next commit"""
+    return repo.copy(*relpath(repo, (source, dest)))
+
 def debugaddchangegroup(ui, repo):
     data = sys.stdin.read()
     repo.addchangegroup(data)
@@ -608,6 +612,7 @@
                    ('d', 'date', "", 'data'),
                    ('u', 'user', "", 'user')],
                   'hg commit [files]'),
+    "copy": (copy, [], 'hg copy <source> <dest>'),
     "debugaddchangegroup": (debugaddchangegroup, [], 'debugaddchangegroup'),
     "debugchangegroup": (debugchangegroup, [], 'debugchangegroup [roots]'),
     "debugindex": (debugindex, [], 'debugindex <file>'),
--- a/mercurial/hg.py	Wed Jun 15 15:50:28 2005 -0800
+++ b/mercurial/hg.py	Wed Jun 15 15:57:07 2005 -0800
@@ -204,6 +204,7 @@
         self.ui = ui
         self.map = None
         self.pl = None
+        self.copies = {}
 
     def __del__(self):
         if self.dirty:
@@ -253,8 +254,19 @@
             l = e[4]
             pos += 17
             f = st[pos:pos + l]
+            if '\0' in f: 
+                f, c = f.split('\0')
+                self.copies[f] = c
             self.map[f] = e[:4]
             pos += l
+
+    def copy(self, source, dest):
+        self.read()
+        self.dirty = 1
+        self.copies[dest] = source
+
+    def copied(self, file):
+        return self.copies.get(file, None)
         
     def update(self, files, state):
         ''' current states:
@@ -292,11 +304,14 @@
         st = self.opener("dirstate", "w")
         st.write("".join(self.pl))
         for f, e in self.map.items():
+            c = self.copied(f)
+            if c:
+                f = f + "\0" + c
             e = struct.pack(">cllll", e[0], e[1], e[2], e[3], len(f))
             st.write(e + f)
         self.dirty = 0
 
-    def copy(self):
+    def dup(self):
         self.read()
         return self.map.copy()
 
@@ -556,10 +571,17 @@
                 self.warn("trouble committing %s!\n" % f)
                 raise
 
+            meta = {}
+            cp = self.dirstate.copied(f)
+            if cp:
+                meta["copy"] = cp
+                meta["copyrev"] = hex(m1.get(cp, m2.get(cp, nullid)))
+                self.ui.debug(" %s: copy %s:%s\n" % (f, cp, meta["copyrev"])) 
+
             r = self.file(f)
             fp1 = m1.get(f, nullid)
             fp2 = m2.get(f, nullid)
-            new[f] = r.add(t, {}, tr, linkrev, fp1, fp2)
+            new[f] = r.add(t, meta, tr, linkrev, fp1, fp2)
 
         # update manifest
         m1.update(new)
@@ -600,7 +622,7 @@
             changeset = self.dirstate.parents()[0]
             change = self.changelog.read(changeset)
             mf = self.manifest.read(change[0])
-            dc = self.dirstate.copy()
+            dc = self.dirstate.dup()
 
         def fcmp(fn):
             t1 = self.wfile(fn).read()
@@ -689,6 +711,15 @@
             else:
                 self.dirstate.update([f], "r")
 
+    def copy(self, source, dest):
+        p = self.wjoin(dest)
+        if not os.path.isfile(dest):
+            self.ui.warn("%s does not exist!\n" % dest)
+        else:
+            if self.dirstate.state(dest) == '?':
+                self.dirstate.update([dest], "a")
+            self.dirstate.copy(source, dest)
+
     def heads(self):
         return self.changelog.heads()
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-copy	Wed Jun 15 15:57:07 2005 -0800
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+set -x
+hg init
+echo a > a
+hg add a
+hg commit -t "1" -u test -d "0 0"
+hg status
+cp a b
+hg copy a b
+hg status
+hg -d commit -t "2" -u test -d "0 0"
+hg history
+hg log a
+hexdump -C .hg/data/b.d
+hg cat b | md5sum
+hg cat a | md5sum
+hg verify
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-copy.out	Wed Jun 15 15:57:07 2005 -0800
@@ -0,0 +1,51 @@
++ hg init
++ echo a
++ hg add a
++ hg commit -t 1 -u test -d '0 0'
++ hg status
+? .out
++ cp a b
++ hg copy a b
++ hg status
+A b
+? .out
++ hg -d commit -t 2 -u test -d '0 0'
+b
+ b: copy a:b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
++ hg history
+changeset:   1:3b5b84850bbed12e8ff8c1b87b32dc93c59ae6d8
+user:        test
+date:        Wed Dec 31 16:00:00 1969
+summary:     2
+
+changeset:   0:c19d34741b0a4ced8e4ba74bb834597d5193851e
+user:        test
+date:        Wed Dec 31 16:00:00 1969
+summary:     1
+
++ hg log a
+revision:    0:b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
+changeset:   0:c19d34741b0a4ced8e4ba74bb834597d5193851e
+user:        test
+date:        Wed Dec 31 16:00:00 1969
+summary:     1
+
++ hexdump -C .hg/data/b.d
+00000000  75 01 0a 63 6f 70 79 72  65 76 3a 20 62 37 38 39  |u..copyrev: b789|
+00000010  66 64 64 39 36 64 63 32  66 33 62 64 32 32 39 63  |fdd96dc2f3bd229c|
+00000020  31 64 64 38 65 65 64 66  30 66 63 36 30 65 32 62  |1dd8eedf0fc60e2b|
+00000030  36 38 65 33 0a 63 6f 70  79 3a 20 61 0a 01 0a 61  |68e3.copy: a...a|
+00000040  0a                                                |.|
+00000041
++ hg cat b
++ md5sum
+60b725f10c9c85c70d97880dfe8191b3  -
++ hg cat a
++ md5sum
+60b725f10c9c85c70d97880dfe8191b3  -
++ hg verify
+checking changesets
+checking manifests
+crosschecking files in changesets and manifests
+checking files
+2 files, 2 changesets, 2 total revisions