Show More
@@ -595,12 +595,10 b' def reposetup(ui, repo):' | |||||
595 | wlock.release() |
|
595 | wlock.release() | |
596 |
|
596 | |||
597 | # monkeypatches |
|
597 | # monkeypatches | |
598 |
def kwpatchfile_init(orig, self, ui, |
|
598 | def kwpatchfile_init(orig, self, ui, gp, backend, store, eolmode=None): | |
599 | remove, eolmode=None, copysource=None): |
|
|||
600 | '''Monkeypatch/wrap patch.patchfile.__init__ to avoid |
|
599 | '''Monkeypatch/wrap patch.patchfile.__init__ to avoid | |
601 | rejects or conflicts due to expanded keywords in working dir.''' |
|
600 | rejects or conflicts due to expanded keywords in working dir.''' | |
602 |
orig(self, ui, |
|
601 | orig(self, ui, gp, backend, store, eolmode) | |
603 | eolmode, copysource) |
|
|||
604 | # shrink keywords read from working dir |
|
602 | # shrink keywords read from working dir | |
605 | self.lines = kwt.shrinklines(self.fname, self.lines) |
|
603 | self.lines = kwt.shrinklines(self.fname, self.lines) | |
606 |
|
604 |
@@ -281,6 +281,14 b' class patchmeta(object):' | |||||
281 | isexec = mode & 0100 |
|
281 | isexec = mode & 0100 | |
282 | self.mode = (islink, isexec) |
|
282 | self.mode = (islink, isexec) | |
283 |
|
283 | |||
|
284 | def copy(self): | |||
|
285 | other = patchmeta(self.path) | |||
|
286 | other.oldpath = self.oldpath | |||
|
287 | other.mode = self.mode | |||
|
288 | other.op = self.op | |||
|
289 | other.binary = self.binary | |||
|
290 | return other | |||
|
291 | ||||
284 | def __repr__(self): |
|
292 | def __repr__(self): | |
285 | return "<patchmeta %s %r>" % (self.op, self.path) |
|
293 | return "<patchmeta %s %r>" % (self.op, self.path) | |
286 |
|
294 | |||
@@ -509,9 +517,8 b" contextdesc = re.compile('(---|\\*\\*\\*) (" | |||||
509 | eolmodes = ['strict', 'crlf', 'lf', 'auto'] |
|
517 | eolmodes = ['strict', 'crlf', 'lf', 'auto'] | |
510 |
|
518 | |||
511 | class patchfile(object): |
|
519 | class patchfile(object): | |
512 |
def __init__(self, ui, |
|
520 | def __init__(self, ui, gp, backend, store, eolmode='strict'): | |
513 | eolmode='strict', copysource=None): |
|
521 | self.fname = gp.path | |
514 | self.fname = fname |
|
|||
515 | self.eolmode = eolmode |
|
522 | self.eolmode = eolmode | |
516 | self.eol = None |
|
523 | self.eol = None | |
517 | self.backend = backend |
|
524 | self.backend = backend | |
@@ -519,17 +526,17 b' class patchfile(object):' | |||||
519 | self.lines = [] |
|
526 | self.lines = [] | |
520 | self.exists = False |
|
527 | self.exists = False | |
521 | self.missing = True |
|
528 | self.missing = True | |
522 | self.mode = mode |
|
529 | self.mode = gp.mode | |
523 |
self.copysource = |
|
530 | self.copysource = gp.oldpath | |
524 | self.create = create |
|
531 | self.create = gp.op in ('ADD', 'COPY', 'RENAME') | |
525 |
self.remove = |
|
532 | self.remove = gp.op == 'DELETE' | |
526 | try: |
|
533 | try: | |
527 | if copysource is None: |
|
534 | if self.copysource is None: | |
528 | data, mode = backend.getfile(fname) |
|
535 | data, mode = backend.getfile(self.fname) | |
529 | self.exists = True |
|
536 | self.exists = True | |
530 | else: |
|
537 | else: | |
531 | data, mode = store.getfile(copysource) |
|
538 | data, mode = store.getfile(self.copysource) | |
532 | self.exists = backend.exists(fname) |
|
539 | self.exists = backend.exists(self.fname) | |
533 | self.missing = False |
|
540 | self.missing = False | |
534 | if data: |
|
541 | if data: | |
535 | self.lines = data.splitlines(True) |
|
542 | self.lines = data.splitlines(True) | |
@@ -549,7 +556,7 b' class patchfile(object):' | |||||
549 | nlines.append(l) |
|
556 | nlines.append(l) | |
550 | self.lines = nlines |
|
557 | self.lines = nlines | |
551 | except IOError: |
|
558 | except IOError: | |
552 | if create: |
|
559 | if self.create: | |
553 | self.missing = False |
|
560 | self.missing = False | |
554 | if self.mode is None: |
|
561 | if self.mode is None: | |
555 | self.mode = (False, False) |
|
562 | self.mode = (False, False) | |
@@ -1016,14 +1023,7 b' def pathstrip(path, strip):' | |||||
1016 | count -= 1 |
|
1023 | count -= 1 | |
1017 | return path[:i].lstrip(), path[i:].rstrip() |
|
1024 | return path[:i].lstrip(), path[i:].rstrip() | |
1018 |
|
1025 | |||
1019 |
def |
|
1026 | def makepatchmeta(backend, afile_orig, bfile_orig, hunk, strip): | |
1020 | if gp: |
|
|||
1021 | # Git patches do not play games. Excluding copies from the |
|
|||
1022 | # following heuristic avoids a lot of confusion |
|
|||
1023 | fname = pathstrip(gp.path, strip - 1)[1] |
|
|||
1024 | create = gp.op in ('ADD', 'COPY', 'RENAME') |
|
|||
1025 | remove = gp.op == 'DELETE' |
|
|||
1026 | return fname, create, remove |
|
|||
1027 | nulla = afile_orig == "/dev/null" |
|
1027 | nulla = afile_orig == "/dev/null" | |
1028 | nullb = bfile_orig == "/dev/null" |
|
1028 | nullb = bfile_orig == "/dev/null" | |
1029 | create = nulla and hunk.starta == 0 and hunk.lena == 0 |
|
1029 | create = nulla and hunk.starta == 0 and hunk.lena == 0 | |
@@ -1065,7 +1065,12 b' def selectfile(backend, afile_orig, bfil' | |||||
1065 | else: |
|
1065 | else: | |
1066 | raise PatchError(_("undefined source and destination files")) |
|
1066 | raise PatchError(_("undefined source and destination files")) | |
1067 |
|
1067 | |||
1068 | return fname, create, remove |
|
1068 | gp = patchmeta(fname) | |
|
1069 | if create: | |||
|
1070 | gp.op = 'ADD' | |||
|
1071 | elif remove: | |||
|
1072 | gp.op = 'DELETE' | |||
|
1073 | return gp | |||
1069 |
|
1074 | |||
1070 | def scangitpatch(lr, firstline): |
|
1075 | def scangitpatch(lr, firstline): | |
1071 | """ |
|
1076 | """ | |
@@ -1134,7 +1139,7 b' def iterhunks(fp):' | |||||
1134 | hunknum += 1 |
|
1139 | hunknum += 1 | |
1135 | if emitfile: |
|
1140 | if emitfile: | |
1136 | emitfile = False |
|
1141 | emitfile = False | |
1137 | yield 'file', (afile, bfile, h, gp) |
|
1142 | yield 'file', (afile, bfile, h, gp and gp.copy() or None) | |
1138 | yield 'hunk', h |
|
1143 | yield 'hunk', h | |
1139 | elif x.startswith('diff --git'): |
|
1144 | elif x.startswith('diff --git'): | |
1140 | m = gitre.match(x) |
|
1145 | m = gitre.match(x) | |
@@ -1144,14 +1149,14 b' def iterhunks(fp):' | |||||
1144 | # scan whole input for git metadata |
|
1149 | # scan whole input for git metadata | |
1145 | gitpatches = [('a/' + gp.path, 'b/' + gp.path, gp) for gp |
|
1150 | gitpatches = [('a/' + gp.path, 'b/' + gp.path, gp) for gp | |
1146 | in scangitpatch(lr, x)] |
|
1151 | in scangitpatch(lr, x)] | |
1147 | yield 'git', [g[2] for g in gitpatches |
|
1152 | yield 'git', [g[2].copy() for g in gitpatches | |
1148 | if g[2].op in ('COPY', 'RENAME')] |
|
1153 | if g[2].op in ('COPY', 'RENAME')] | |
1149 | gitpatches.reverse() |
|
1154 | gitpatches.reverse() | |
1150 | afile = 'a/' + m.group(1) |
|
1155 | afile = 'a/' + m.group(1) | |
1151 | bfile = 'b/' + m.group(2) |
|
1156 | bfile = 'b/' + m.group(2) | |
1152 | while afile != gitpatches[-1][0] and bfile != gitpatches[-1][1]: |
|
1157 | while afile != gitpatches[-1][0] and bfile != gitpatches[-1][1]: | |
1153 | gp = gitpatches.pop()[2] |
|
1158 | gp = gitpatches.pop()[2] | |
1154 | yield 'file', ('a/' + gp.path, 'b/' + gp.path, None, gp) |
|
1159 | yield 'file', ('a/' + gp.path, 'b/' + gp.path, None, gp.copy()) | |
1155 | gp = gitpatches[-1][2] |
|
1160 | gp = gitpatches[-1][2] | |
1156 | # copy/rename + modify should modify target, not source |
|
1161 | # copy/rename + modify should modify target, not source | |
1157 | if gp.op in ('COPY', 'DELETE', 'RENAME', 'ADD') or gp.mode: |
|
1162 | if gp.op in ('COPY', 'DELETE', 'RENAME', 'ADD') or gp.mode: | |
@@ -1191,7 +1196,7 b' def iterhunks(fp):' | |||||
1191 |
|
1196 | |||
1192 | while gitpatches: |
|
1197 | while gitpatches: | |
1193 | gp = gitpatches.pop()[2] |
|
1198 | gp = gitpatches.pop()[2] | |
1194 | yield 'file', ('a/' + gp.path, 'b/' + gp.path, None, gp) |
|
1199 | yield 'file', ('a/' + gp.path, 'b/' + gp.path, None, gp.copy()) | |
1195 |
|
1200 | |||
1196 | def applydiff(ui, fp, backend, store, strip=1, eolmode='strict'): |
|
1201 | def applydiff(ui, fp, backend, store, strip=1, eolmode='strict'): | |
1197 | """Reads a patch from fp and tries to apply it. |
|
1202 | """Reads a patch from fp and tries to apply it. | |
@@ -1228,41 +1233,38 b' def _applydiff(ui, fp, patcher, backend,' | |||||
1228 | rejects += current_file.close() |
|
1233 | rejects += current_file.close() | |
1229 | current_file = None |
|
1234 | current_file = None | |
1230 | afile, bfile, first_hunk, gp = values |
|
1235 | afile, bfile, first_hunk, gp = values | |
1231 | copysource = None |
|
|||
1232 | if gp: |
|
1236 | if gp: | |
1233 | path = pstrip(gp.path) |
|
1237 | path = pstrip(gp.path) | |
|
1238 | gp.path = pstrip(gp.path) | |||
1234 | if gp.oldpath: |
|
1239 | if gp.oldpath: | |
1235 |
|
|
1240 | gp.oldpath = pstrip(gp.oldpath) | |
1236 | if gp.op == 'RENAME': |
|
1241 | else: | |
1237 | backend.unlink(copysource) |
|
1242 | gp = makepatchmeta(backend, afile, bfile, first_hunk, strip) | |
1238 | if not first_hunk: |
|
1243 | if gp.op == 'RENAME': | |
1239 | if gp.op == 'DELETE': |
|
1244 | backend.unlink(gp.oldpath) | |
1240 | backend.unlink(path) |
|
|||
1241 | continue |
|
|||
1242 | data, mode = None, None |
|
|||
1243 | if gp.op in ('RENAME', 'COPY'): |
|
|||
1244 | data, mode = store.getfile(copysource) |
|
|||
1245 | if gp.mode: |
|
|||
1246 | mode = gp.mode |
|
|||
1247 | if gp.op == 'ADD': |
|
|||
1248 | # Added files without content have no hunk and |
|
|||
1249 | # must be created |
|
|||
1250 | data = '' |
|
|||
1251 | if data or mode: |
|
|||
1252 | if (gp.op in ('ADD', 'RENAME', 'COPY') |
|
|||
1253 | and backend.exists(path)): |
|
|||
1254 | raise PatchError(_("cannot create %s: destination " |
|
|||
1255 | "already exists") % path) |
|
|||
1256 | backend.setfile(path, data, mode, copysource) |
|
|||
1257 | if not first_hunk: |
|
1245 | if not first_hunk: | |
|
1246 | if gp.op == 'DELETE': | |||
|
1247 | backend.unlink(gp.path) | |||
|
1248 | continue | |||
|
1249 | data, mode = None, None | |||
|
1250 | if gp.op in ('RENAME', 'COPY'): | |||
|
1251 | data, mode = store.getfile(gp.oldpath) | |||
|
1252 | if gp.mode: | |||
|
1253 | mode = gp.mode | |||
|
1254 | if gp.op == 'ADD': | |||
|
1255 | # Added files without content have no hunk and | |||
|
1256 | # must be created | |||
|
1257 | data = '' | |||
|
1258 | if data or mode: | |||
|
1259 | if (gp.op in ('ADD', 'RENAME', 'COPY') | |||
|
1260 | and backend.exists(gp.path)): | |||
|
1261 | raise PatchError(_("cannot create %s: destination " | |||
|
1262 | "already exists") % gp.path) | |||
|
1263 | backend.setfile(gp.path, data, mode, gp.oldpath) | |||
1258 | continue |
|
1264 | continue | |
1259 | try: |
|
1265 | try: | |
1260 | mode = gp and gp.mode or None |
|
1266 | current_file = patcher(ui, gp, backend, store, | |
1261 | current_file, create, remove = selectfile( |
|
1267 | eolmode=eolmode) | |
1262 | backend, afile, bfile, first_hunk, strip, gp) |
|
|||
1263 | current_file = patcher(ui, current_file, backend, store, mode, |
|
|||
1264 | create, remove, eolmode=eolmode, |
|
|||
1265 | copysource=copysource) |
|
|||
1266 | except PatchError, inst: |
|
1268 | except PatchError, inst: | |
1267 | ui.warn(str(inst) + '\n') |
|
1269 | ui.warn(str(inst) + '\n') | |
1268 | current_file = None |
|
1270 | current_file = None | |
@@ -1395,14 +1397,14 b' def changedfiles(ui, repo, patchpath, st' | |||||
1395 | if state == 'file': |
|
1397 | if state == 'file': | |
1396 | afile, bfile, first_hunk, gp = values |
|
1398 | afile, bfile, first_hunk, gp = values | |
1397 | if gp: |
|
1399 | if gp: | |
1398 |
|
|
1400 | gp.path = pathstrip(gp.path, strip - 1)[1] | |
1399 |
if gp.o |
|
1401 | if gp.oldpath: | |
1400 |
|
|
1402 | gp.oldpath = pathstrip(gp.oldpath, strip - 1)[1] | |
1401 |
|
|
1403 | else: | |
1402 | continue |
|
1404 | gp = makepatchmeta(backend, afile, bfile, first_hunk, strip) | |
1403 | current_file, create, remove = selectfile( |
|
1405 | changed.add(gp.path) | |
1404 | backend, afile, bfile, first_hunk, strip, gp) |
|
1406 | if gp.op == 'RENAME': | |
1405 |
changed.add( |
|
1407 | changed.add(gp.oldpath) | |
1406 | elif state not in ('hunk', 'git'): |
|
1408 | elif state not in ('hunk', 'git'): | |
1407 | raise util.Abort(_('unsupported parser state: %s') % state) |
|
1409 | raise util.Abort(_('unsupported parser state: %s') % state) | |
1408 | return changed |
|
1410 | return changed |
General Comments 0
You need to be logged in to leave comments.
Login now