Show More
@@ -595,11 +595,11 b' def reposetup(ui, repo):' | |||
|
595 | 595 | wlock.release() |
|
596 | 596 | |
|
597 | 597 | # monkeypatches |
|
598 | def kwpatchfile_init(orig, self, ui, fname, backend, | |
|
598 | def kwpatchfile_init(orig, self, ui, fname, backend, mode, | |
|
599 | 599 | missing=False, eolmode=None): |
|
600 | 600 | '''Monkeypatch/wrap patch.patchfile.__init__ to avoid |
|
601 | 601 | rejects or conflicts due to expanded keywords in working dir.''' |
|
602 | orig(self, ui, fname, backend, missing, eolmode) | |
|
602 | orig(self, ui, fname, backend, mode, missing, eolmode) | |
|
603 | 603 | # shrink keywords read from working dir |
|
604 | 604 | self.lines = kwt.shrinklines(self.fname, self.lines) |
|
605 | 605 |
@@ -372,8 +372,10 b' class abstractbackend(object):' | |||
|
372 | 372 | """ |
|
373 | 373 | raise NotImplementedError |
|
374 | 374 | |
|
375 | def writelines(self, fname, lines): | |
|
376 |
"""Write lines to target file. |
|
|
375 | def writelines(self, fname, lines, mode): | |
|
376 | """Write lines to target file. mode is a (islink, isexec) | |
|
377 | tuple, or None if there is no mode information. | |
|
378 | """ | |
|
377 | 379 | raise NotImplementedError |
|
378 | 380 | |
|
379 | 381 | def unlink(self, fname): |
@@ -397,6 +399,10 b' class abstractbackend(object):' | |||
|
397 | 399 | def exists(self, fname): |
|
398 | 400 | raise NotImplementedError |
|
399 | 401 | |
|
402 | def setmode(self, fname, islink, isexec): | |
|
403 | """Change target file mode.""" | |
|
404 | raise NotImplementedError | |
|
405 | ||
|
400 | 406 | class fsbackend(abstractbackend): |
|
401 | 407 | def __init__(self, ui, basedir): |
|
402 | 408 | super(fsbackend, self).__init__(ui) |
@@ -414,29 +420,24 b' class fsbackend(abstractbackend):' | |||
|
414 | 420 | finally: |
|
415 | 421 | fp.close() |
|
416 | 422 | |
|
417 | def writelines(self, fname, lines): | |
|
418 | # Ensure supplied data ends in fname, being a regular file or | |
|
419 | # a symlink. _updatedir will -too magically- take care | |
|
420 | # of setting it to the proper type afterwards. | |
|
421 | st_mode = None | |
|
422 | islink = os.path.islink(self._join(fname)) | |
|
423 | if islink: | |
|
424 | fp = cStringIO.StringIO() | |
|
425 | else: | |
|
423 | def writelines(self, fname, lines, mode): | |
|
424 | if not mode: | |
|
425 | # Preserve mode information | |
|
426 | isexec, islink = False, False | |
|
426 | 427 | try: |
|
427 |
|
|
|
428 | isexec = os.lstat(self._join(fname)).st_mode & 0100 != 0 | |
|
429 | islink = os.path.islink(self._join(fname)) | |
|
428 | 430 | except OSError, e: |
|
429 | 431 | if e.errno != errno.ENOENT: |
|
430 | 432 | raise |
|
431 | fp = self.opener(fname, 'w') | |
|
432 | try: | |
|
433 | fp.writelines(lines) | |
|
434 | if islink: | |
|
435 | self.opener.symlink(fp.getvalue(), fname) | |
|
436 | if st_mode is not None: | |
|
437 | os.chmod(self._join(fname), st_mode) | |
|
438 | finally: | |
|
439 | fp.close() | |
|
433 | else: | |
|
434 | islink, isexec = mode | |
|
435 | if islink: | |
|
436 | self.opener.symlink(''.join(lines), fname) | |
|
437 | else: | |
|
438 | self.opener(fname, 'w').writelines(lines) | |
|
439 | if isexec: | |
|
440 | util.setflags(self._join(fname), False, True) | |
|
440 | 441 | |
|
441 | 442 | def unlink(self, fname): |
|
442 | 443 | os.unlink(self._join(fname)) |
@@ -470,13 +471,17 b' class fsbackend(abstractbackend):' | |||
|
470 | 471 | def exists(self, fname): |
|
471 | 472 | return os.path.lexists(self._join(fname)) |
|
472 | 473 | |
|
474 | def setmode(self, fname, islink, isexec): | |
|
475 | util.setflags(self._join(fname), islink, isexec) | |
|
476 | ||
|
473 | 477 | # @@ -start,len +start,len @@ or @@ -start +start @@ if len is 1 |
|
474 | 478 | unidesc = re.compile('@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@') |
|
475 | 479 | contextdesc = re.compile('(---|\*\*\*) (\d+)(,(\d+))? (---|\*\*\*)') |
|
476 | 480 | eolmodes = ['strict', 'crlf', 'lf', 'auto'] |
|
477 | 481 | |
|
478 | 482 | class patchfile(object): |
|
479 |
def __init__(self, ui, fname, backend, missing=False, |
|
|
483 | def __init__(self, ui, fname, backend, mode, missing=False, | |
|
484 | eolmode='strict'): | |
|
480 | 485 | self.fname = fname |
|
481 | 486 | self.eolmode = eolmode |
|
482 | 487 | self.eol = None |
@@ -485,6 +490,7 b' class patchfile(object):' | |||
|
485 | 490 | self.lines = [] |
|
486 | 491 | self.exists = False |
|
487 | 492 | self.missing = missing |
|
493 | self.mode = mode | |
|
488 | 494 | if not missing: |
|
489 | 495 | try: |
|
490 | 496 | self.lines = self.backend.readlines(fname) |
@@ -516,7 +522,7 b' class patchfile(object):' | |||
|
516 | 522 | self.printfile(False) |
|
517 | 523 | self.hunks = 0 |
|
518 | 524 | |
|
519 | def writelines(self, fname, lines): | |
|
525 | def writelines(self, fname, lines, mode): | |
|
520 | 526 | if self.eolmode == 'auto': |
|
521 | 527 | eol = self.eol |
|
522 | 528 | elif self.eolmode == 'crlf': |
@@ -532,7 +538,7 b' class patchfile(object):' | |||
|
532 | 538 | rawlines.append(l) |
|
533 | 539 | lines = rawlines |
|
534 | 540 | |
|
535 | self.backend.writelines(fname, lines) | |
|
541 | self.backend.writelines(fname, lines, mode) | |
|
536 | 542 | |
|
537 | 543 | def printfile(self, warn): |
|
538 | 544 | if self.fileprinted: |
@@ -670,7 +676,7 b' class patchfile(object):' | |||
|
670 | 676 | |
|
671 | 677 | def close(self): |
|
672 | 678 | if self.dirty: |
|
673 | self.writelines(self.fname, self.lines) | |
|
679 | self.writelines(self.fname, self.lines, self.mode) | |
|
674 | 680 | self.write_rej() |
|
675 | 681 | return len(self.rej) |
|
676 | 682 | |
@@ -1087,14 +1093,16 b' def iterhunks(fp):' | |||
|
1087 | 1093 | hunknum += 1 |
|
1088 | 1094 | if emitfile: |
|
1089 | 1095 | emitfile = False |
|
1090 | yield 'file', (afile, bfile, h) | |
|
1096 | yield 'file', (afile, bfile, h, gpatch and gpatch.mode or None) | |
|
1091 | 1097 | yield 'hunk', h |
|
1092 | 1098 | elif state == BFILE and x.startswith('GIT binary patch'): |
|
1093 |
h = |
|
|
1099 | gpatch = changed[bfile] | |
|
1100 | h = binhunk(gpatch) | |
|
1094 | 1101 | hunknum += 1 |
|
1095 | 1102 | if emitfile: |
|
1096 | 1103 | emitfile = False |
|
1097 |
yield 'file', ('a/' + afile, 'b/' + bfile, h |
|
|
1104 | yield 'file', ('a/' + afile, 'b/' + bfile, h, | |
|
1105 | gpatch and gpatch.mode or None) | |
|
1098 | 1106 | h.extract(lr) |
|
1099 | 1107 | yield 'hunk', h |
|
1100 | 1108 | elif x.startswith('diff --git'): |
@@ -1181,11 +1189,11 b' def _applydiff(ui, fp, patcher, backend,' | |||
|
1181 | 1189 | elif state == 'file': |
|
1182 | 1190 | if current_file: |
|
1183 | 1191 | rejects += current_file.close() |
|
1184 | afile, bfile, first_hunk = values | |
|
1192 | afile, bfile, first_hunk, mode = values | |
|
1185 | 1193 | try: |
|
1186 | 1194 | current_file, missing = selectfile(backend, afile, bfile, |
|
1187 | 1195 | first_hunk, strip) |
|
1188 | current_file = patcher(ui, current_file, backend, | |
|
1196 | current_file = patcher(ui, current_file, backend, mode, | |
|
1189 | 1197 | missing=missing, eolmode=eolmode) |
|
1190 | 1198 | except PatchError, inst: |
|
1191 | 1199 | ui.warn(str(inst) + '\n') |
@@ -1208,6 +1216,16 b' def _applydiff(ui, fp, patcher, backend,' | |||
|
1208 | 1216 | if current_file: |
|
1209 | 1217 | rejects += current_file.close() |
|
1210 | 1218 | |
|
1219 | # Handle mode changes without hunk | |
|
1220 | for gp in changed.itervalues(): | |
|
1221 | if not gp or not gp.mode: | |
|
1222 | continue | |
|
1223 | if gp.op == 'ADD' and not backend.exists(gp.path): | |
|
1224 | # Added files without content have no hunk and must be created | |
|
1225 | backend.writelines(gp.path, [], gp.mode) | |
|
1226 | else: | |
|
1227 | backend.setmode(gp.path, gp.mode[0], gp.mode[1]) | |
|
1228 | ||
|
1211 | 1229 | if rejects: |
|
1212 | 1230 | return -1 |
|
1213 | 1231 | return err |
@@ -1240,16 +1258,6 b' def _updatedir(ui, repo, patches, simila' | |||
|
1240 | 1258 | if (not similarity) and removes: |
|
1241 | 1259 | wctx.remove(sorted(removes), True) |
|
1242 | 1260 | |
|
1243 | for f in patches: | |
|
1244 | gp = patches[f] | |
|
1245 | if gp and gp.mode: | |
|
1246 | islink, isexec = gp.mode | |
|
1247 | dst = repo.wjoin(gp.path) | |
|
1248 | # patch won't create empty files | |
|
1249 | if gp.op == 'ADD' and not os.path.lexists(dst): | |
|
1250 | flags = (isexec and 'x' or '') + (islink and 'l' or '') | |
|
1251 | repo.wwrite(gp.path, '', flags) | |
|
1252 | util.setflags(dst, islink, isexec) | |
|
1253 | 1261 | scmutil.addremove(repo, cfiles, similarity=similarity) |
|
1254 | 1262 | files = patches.keys() |
|
1255 | 1263 | files.extend([r for r in removes if r not in files]) |
@@ -1359,7 +1367,7 b' def changedfiles(ui, repo, patchpath, st' | |||
|
1359 | 1367 | if state == 'hunk': |
|
1360 | 1368 | continue |
|
1361 | 1369 | elif state == 'file': |
|
1362 | afile, bfile, first_hunk = values | |
|
1370 | afile, bfile, first_hunk, mode = values | |
|
1363 | 1371 | current_file, missing = selectfile(backend, afile, bfile, |
|
1364 | 1372 | first_hunk, strip) |
|
1365 | 1373 | changed.add(current_file) |
General Comments 0
You need to be logged in to leave comments.
Login now