##// END OF EJS Templates
Merge with stable
Matt Mackall -
r4335:f4a1eac5 merge default
parent child Browse files
Show More
@@ -0,0 +1,39 b''
1 #!/bin/sh
2
3 # Test issue 529 - mq aborts when merging patch deleting files
4
5 rewrite_path()
6 {
7 sed -e 's:\\:/:g' -e 's:[^ ]*/t/::g'
8 }
9
10 echo "[extensions]" >> $HGRCPATH
11 echo "hgext.mq=" >> $HGRCPATH
12
13 # Commit two dummy files in "init" changeset
14 hg init t
15 cd t
16 echo a > a
17 echo b > b
18 hg ci -Am init
19 hg tag -l init
20
21 # Create a patch removing a
22 hg qnew rm_a
23 hg rm a
24 hg qrefresh -m "rm a"
25
26 # Save the patch queue so we can merge it later
27 hg qsave -c -e 2>&1 | rewrite_path
28
29 # Update b and commit in an "update" changeset
30 hg up -C init
31 echo b >> b
32 hg st
33 hg ci -m update
34
35 # Here, qpush used to abort with :
36 # The system cannot find the file specified => a
37 hg manifest
38 hg qpush -a -m 2>&1 | rewrite_path
39 hg manifest
@@ -0,0 +1,11 b''
1 adding a
2 adding b
3 copy .hg/patches to .hg/patches.1
4 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
5 M b
6 a
7 b
8 merging with queue at: .hg/patches.1
9 applying rm_a
10 Now at: rm_a
11 b
@@ -471,8 +471,16 b' class queue:'
471 471 patcherr = not patcherr
472 472
473 473 if merge and files:
474 # Mark as merged and update dirstate parent info
475 repo.dirstate.update(repo.dirstate.filterfiles(files.keys()), 'm')
474 # Mark as removed/merged and update dirstate parent info
475 removed = []
476 merged = []
477 for f in files:
478 if os.path.exists(repo.dirstate.wjoin(f)):
479 merged.append(f)
480 else:
481 removed.append(f)
482 repo.dirstate.update(repo.dirstate.filterfiles(removed), 'r')
483 repo.dirstate.update(repo.dirstate.filterfiles(merged), 'm')
476 484 p1, p2 = repo.dirstate.parents()
477 485 repo.dirstate.setparents(p1, merge)
478 486 files = patch.updatedir(self.ui, repo, files, wlock=wlock)
@@ -314,7 +314,7 b' class dirstate(object):'
314 314 def write(self):
315 315 if not self.dirty:
316 316 return
317 st = self.opener("dirstate", "w", atomic=True)
317 st = self.opener("dirstate", "w", atomictemp=True)
318 318 st.write("".join(self.pl))
319 319 for f, e in self.map.items():
320 320 c = self.copied(f)
@@ -322,6 +322,7 b' class dirstate(object):'
322 322 f = f + "\0" + c
323 323 e = struct.pack(self.format, e[0], e[1], e[2], e[3], len(f))
324 324 st.write(e + f)
325 st.rename()
325 326 self.dirty = 0
326 327
327 328 def filterfiles(self, files):
@@ -417,10 +417,11 b' class localrepository(repo.repository):'
417 417
418 418 def _writebranchcache(self, branches, tip, tiprev):
419 419 try:
420 f = self.opener("branch.cache", "w")
420 f = self.opener("branch.cache", "w", atomictemp=True)
421 421 f.write("%s %s\n" % (hex(tip), tiprev))
422 422 for label, node in branches.iteritems():
423 423 f.write("%s %s\n" % (hex(node), label))
424 f.rename()
424 425 except IOError:
425 426 pass
426 427
@@ -27,7 +27,7 b' class templater(object):'
27 27 is treated as name of template file.
28 28
29 29 templater is asked to expand a key in map. it looks up key, and
30 looks for atrings like this: {foo}. it expands {foo} by looking up
30 looks for strings like this: {foo}. it expands {foo} by looking up
31 31 foo in map, and substituting it. expansion is recursive: it stops
32 32 when there is no more {foo} to replace.
33 33
@@ -766,6 +766,9 b' def checkfolding(path):'
766 766 except:
767 767 return True
768 768
769 _umask = os.umask(0)
770 os.umask(_umask)
771
769 772 def checkexec(path):
770 773 """
771 774 Check whether the given path is on a filesystem with UNIX-like exec flags
@@ -1103,18 +1106,32 b' def opener(base, audit=True):'
1103 1106 p = base
1104 1107 audit_p = audit
1105 1108
1106 def mktempcopy(name):
1109 def mktempcopy(name, emptyok=False):
1107 1110 d, fn = os.path.split(name)
1108 1111 fd, temp = tempfile.mkstemp(prefix='.%s-' % fn, dir=d)
1109 1112 os.close(fd)
1110 ofp = posixfile(temp, "wb")
1113 # Temporary files are created with mode 0600, which is usually not
1114 # what we want. If the original file already exists, just copy
1115 # its mode. Otherwise, manually obey umask.
1116 try:
1117 st_mode = os.lstat(name).st_mode
1118 except OSError, inst:
1119 if inst.errno != errno.ENOENT:
1120 raise
1121 st_mode = 0666 & ~_umask
1122 os.chmod(temp, st_mode)
1123 if emptyok:
1124 return temp
1111 1125 try:
1112 1126 try:
1113 1127 ifp = posixfile(name, "rb")
1114 1128 except IOError, inst:
1129 if inst.errno == errno.ENOENT:
1130 return temp
1115 1131 if not getattr(inst, 'filename', None):
1116 1132 inst.filename = name
1117 1133 raise
1134 ofp = posixfile(temp, "wb")
1118 1135 for chunk in filechunkiter(ifp):
1119 1136 ofp.write(chunk)
1120 1137 ifp.close()
@@ -1123,15 +1140,13 b' def opener(base, audit=True):'
1123 1140 try: os.unlink(temp)
1124 1141 except: pass
1125 1142 raise
1126 st = os.lstat(name)
1127 os.chmod(temp, st.st_mode)
1128 1143 return temp
1129 1144
1130 1145 class atomictempfile(posixfile):
1131 1146 """the file will only be copied when rename is called"""
1132 1147 def __init__(self, name, mode):
1133 1148 self.__name = name
1134 self.temp = mktempcopy(name)
1149 self.temp = mktempcopy(name, emptyok=('w' in mode))
1135 1150 posixfile.__init__(self, self.temp, mode)
1136 1151 def rename(self):
1137 1152 if not self.closed:
@@ -1165,16 +1180,16 b' def opener(base, audit=True):'
1165 1180 try:
1166 1181 nlink = nlinks(f)
1167 1182 except OSError:
1183 nlink = 0
1168 1184 d = os.path.dirname(f)
1169 1185 if not os.path.isdir(d):
1170 1186 os.makedirs(d)
1171 else:
1172 if atomic:
1173 return atomicfile(f, mode)
1174 elif atomictemp:
1175 return atomictempfile(f, mode)
1176 if nlink > 1:
1177 rename(mktempcopy(f), f)
1187 if atomic:
1188 return atomicfile(f, mode)
1189 elif atomictemp:
1190 return atomictempfile(f, mode)
1191 if nlink > 1:
1192 rename(mktempcopy(f), f)
1178 1193 return posixfile(f, mode)
1179 1194
1180 1195 return o
General Comments 0
You need to be logged in to leave comments. Login now