diff hgext/largefiles/reposetup.py @ 15663:9036c7d106bf stable

largefiles: handle merges between normal files and largefiles (issue3084) The largefiles extension prevents users from adding a normal file named 'foo' if there is already a largefile with the same name. However, there was a loop-hole: when merging, it was possible to bring in a normal file named 'foo' while also having a '.hglf/foo' file. This patch fixes this by extending the manifest merge to deal with these kinds of conflicts. If there is a normal file 'foo' in the working copy, and the other parent brings in a '.hglf/foo' file, then the user will be prompted to keep the normal file or the largefile. Likewise for the symmetric case where a normal file is brought in via the second parent. The prompt looks like this: $ hg merge foo has been turned into a largefile use (l)argefile or keep as (n)ormal file? After the merge, either the '.hglf/foo' file or the 'foo' file will have been deleted. This would cause status to return output like: $ hg status M foo R foo To fix this, the lfiles_repo.status method is changed so that a removed normal file isn't shown if there is largefile with the same name, and vice versa for largefiles.
author Martin Geisler <mg@aragost.com>
date Fri, 09 Dec 2011 17:35:00 +0100
parents 5b66e55c0d93
children 7b7f03502b5a
line wrap: on
line diff
--- a/hgext/largefiles/reposetup.py	Wed Dec 14 15:41:08 2011 +0100
+++ b/hgext/largefiles/reposetup.py	Fri Dec 09 17:35:00 2011 +0100
@@ -192,9 +192,18 @@
                             continue
                         if lfile not in lfdirstate:
                             removed.append(lfile)
-                    # Handle unknown and ignored differently
-                    lfiles = (modified, added, removed, missing, [], [], clean)
+
+                    # Filter result lists
                     result = list(result)
+
+                    # Largefiles are not really removed when they're
+                    # still in the normal dirstate. Likewise, normal
+                    # files are not really removed if it's still in
+                    # lfdirstate. This happens in merges where files
+                    # change type.
+                    removed = [f for f in removed if f not in repo.dirstate]
+                    result[2] = [f for f in result[2] if f not in lfdirstate]
+
                     # Unknown files
                     result[4] = [f for f in unknown
                                  if (repo.dirstate[f] == '?' and
@@ -206,6 +215,7 @@
                     normals = [[fn for fn in filelist
                                 if not lfutil.isstandin(fn)]
                                for filelist in result]
+                    lfiles = (modified, added, removed, missing, [], [], clean)
                     result = [sorted(list1 + list2)
                               for (list1, list2) in zip(normals, lfiles)]
                 else: