Show More
@@ -8,16 +8,16 | |||||
8 | from node import hex, nullid, nullrev, short |
|
8 | from node import hex, nullid, nullrev, short | |
9 | from i18n import _ |
|
9 | from i18n import _ | |
10 | import os, sys, errno, re, tempfile |
|
10 | import os, sys, errno, re, tempfile | |
11 |
import util, scmutil, templater, patch, error, templatekw |
|
11 | import util, scmutil, templater, patch, error, templatekw | |
12 | import match as matchmod |
|
12 | import match as matchmod | |
13 | import subrepo |
|
13 | import subrepo | |
14 |
|
14 | |||
15 |
expandpats = |
|
15 | expandpats = scmutil.expandpats | |
16 |
match = |
|
16 | match = scmutil.match | |
17 |
matchall = |
|
17 | matchall = scmutil.matchall | |
18 |
matchfiles = |
|
18 | matchfiles = scmutil.matchfiles | |
19 |
addremove = |
|
19 | addremove = scmutil.addremove | |
20 |
dirstatecopy = |
|
20 | dirstatecopy = scmutil.dirstatecopy | |
21 |
|
21 | |||
22 | def parsealiases(cmd): |
|
22 | def parsealiases(cmd): | |
23 | return cmd.lstrip("^").split("|") |
|
23 | return cmd.lstrip("^").split("|") |
@@ -6,8 +6,9 | |||||
6 | # GNU General Public License version 2 or any later version. |
|
6 | # GNU General Public License version 2 or any later version. | |
7 |
|
7 | |||
8 | from i18n import _ |
|
8 | from i18n import _ | |
9 | import util, error, osutil, revset |
|
9 | import util, error, osutil, revset, similar | |
10 | import os, errno, stat, sys |
|
10 | import match as matchmod | |
|
11 | import os, errno, stat, sys, glob | |||
11 |
|
12 | |||
12 | def checkfilename(f): |
|
13 | def checkfilename(f): | |
13 | '''Check that the filename f is an acceptable filename for a tracked file''' |
|
14 | '''Check that the filename f is an acceptable filename for a tracked file''' | |
@@ -536,3 +537,154 def revrange(repo, revs): | |||||
536 | seen.update(l) |
|
537 | seen.update(l) | |
537 |
|
538 | |||
538 | return l |
|
539 | return l | |
|
540 | ||||
|
541 | def expandpats(pats): | |||
|
542 | if not util.expandglobs: | |||
|
543 | return list(pats) | |||
|
544 | ret = [] | |||
|
545 | for p in pats: | |||
|
546 | kind, name = matchmod._patsplit(p, None) | |||
|
547 | if kind is None: | |||
|
548 | try: | |||
|
549 | globbed = glob.glob(name) | |||
|
550 | except re.error: | |||
|
551 | globbed = [name] | |||
|
552 | if globbed: | |||
|
553 | ret.extend(globbed) | |||
|
554 | continue | |||
|
555 | ret.append(p) | |||
|
556 | return ret | |||
|
557 | ||||
|
558 | def match(repo, pats=[], opts={}, globbed=False, default='relpath'): | |||
|
559 | if pats == ("",): | |||
|
560 | pats = [] | |||
|
561 | if not globbed and default == 'relpath': | |||
|
562 | pats = expandpats(pats or []) | |||
|
563 | m = matchmod.match(repo.root, repo.getcwd(), pats, | |||
|
564 | opts.get('include'), opts.get('exclude'), default, | |||
|
565 | auditor=repo.auditor) | |||
|
566 | def badfn(f, msg): | |||
|
567 | repo.ui.warn("%s: %s\n" % (m.rel(f), msg)) | |||
|
568 | m.bad = badfn | |||
|
569 | return m | |||
|
570 | ||||
|
571 | def matchall(repo): | |||
|
572 | return matchmod.always(repo.root, repo.getcwd()) | |||
|
573 | ||||
|
574 | def matchfiles(repo, files): | |||
|
575 | return matchmod.exact(repo.root, repo.getcwd(), files) | |||
|
576 | ||||
|
577 | def addremove(repo, pats=[], opts={}, dry_run=None, similarity=None): | |||
|
578 | if dry_run is None: | |||
|
579 | dry_run = opts.get('dry_run') | |||
|
580 | if similarity is None: | |||
|
581 | similarity = float(opts.get('similarity') or 0) | |||
|
582 | # we'd use status here, except handling of symlinks and ignore is tricky | |||
|
583 | added, unknown, deleted, removed = [], [], [], [] | |||
|
584 | audit_path = pathauditor(repo.root) | |||
|
585 | m = match(repo, pats, opts) | |||
|
586 | for abs in repo.walk(m): | |||
|
587 | target = repo.wjoin(abs) | |||
|
588 | good = True | |||
|
589 | try: | |||
|
590 | audit_path(abs) | |||
|
591 | except (OSError, util.Abort): | |||
|
592 | good = False | |||
|
593 | rel = m.rel(abs) | |||
|
594 | exact = m.exact(abs) | |||
|
595 | if good and abs not in repo.dirstate: | |||
|
596 | unknown.append(abs) | |||
|
597 | if repo.ui.verbose or not exact: | |||
|
598 | repo.ui.status(_('adding %s\n') % ((pats and rel) or abs)) | |||
|
599 | elif repo.dirstate[abs] != 'r' and (not good or not os.path.lexists(target) | |||
|
600 | or (os.path.isdir(target) and not os.path.islink(target))): | |||
|
601 | deleted.append(abs) | |||
|
602 | if repo.ui.verbose or not exact: | |||
|
603 | repo.ui.status(_('removing %s\n') % ((pats and rel) or abs)) | |||
|
604 | # for finding renames | |||
|
605 | elif repo.dirstate[abs] == 'r': | |||
|
606 | removed.append(abs) | |||
|
607 | elif repo.dirstate[abs] == 'a': | |||
|
608 | added.append(abs) | |||
|
609 | copies = {} | |||
|
610 | if similarity > 0: | |||
|
611 | for old, new, score in similar.findrenames(repo, | |||
|
612 | added + unknown, removed + deleted, similarity): | |||
|
613 | if repo.ui.verbose or not m.exact(old) or not m.exact(new): | |||
|
614 | repo.ui.status(_('recording removal of %s as rename to %s ' | |||
|
615 | '(%d%% similar)\n') % | |||
|
616 | (m.rel(old), m.rel(new), score * 100)) | |||
|
617 | copies[new] = old | |||
|
618 | ||||
|
619 | if not dry_run: | |||
|
620 | wctx = repo[None] | |||
|
621 | wlock = repo.wlock() | |||
|
622 | try: | |||
|
623 | wctx.remove(deleted) | |||
|
624 | wctx.add(unknown) | |||
|
625 | for new, old in copies.iteritems(): | |||
|
626 | wctx.copy(old, new) | |||
|
627 | finally: | |||
|
628 | wlock.release() | |||
|
629 | ||||
|
630 | def updatedir(ui, repo, patches, similarity=0): | |||
|
631 | '''Update dirstate after patch application according to metadata''' | |||
|
632 | if not patches: | |||
|
633 | return [] | |||
|
634 | copies = [] | |||
|
635 | removes = set() | |||
|
636 | cfiles = patches.keys() | |||
|
637 | cwd = repo.getcwd() | |||
|
638 | if cwd: | |||
|
639 | cfiles = [util.pathto(repo.root, cwd, f) for f in patches.keys()] | |||
|
640 | for f in patches: | |||
|
641 | gp = patches[f] | |||
|
642 | if not gp: | |||
|
643 | continue | |||
|
644 | if gp.op == 'RENAME': | |||
|
645 | copies.append((gp.oldpath, gp.path)) | |||
|
646 | removes.add(gp.oldpath) | |||
|
647 | elif gp.op == 'COPY': | |||
|
648 | copies.append((gp.oldpath, gp.path)) | |||
|
649 | elif gp.op == 'DELETE': | |||
|
650 | removes.add(gp.path) | |||
|
651 | ||||
|
652 | wctx = repo[None] | |||
|
653 | for src, dst in copies: | |||
|
654 | dirstatecopy(ui, repo, wctx, src, dst, cwd=cwd) | |||
|
655 | if (not similarity) and removes: | |||
|
656 | wctx.remove(sorted(removes), True) | |||
|
657 | ||||
|
658 | for f in patches: | |||
|
659 | gp = patches[f] | |||
|
660 | if gp and gp.mode: | |||
|
661 | islink, isexec = gp.mode | |||
|
662 | dst = repo.wjoin(gp.path) | |||
|
663 | # patch won't create empty files | |||
|
664 | if gp.op == 'ADD' and not os.path.lexists(dst): | |||
|
665 | flags = (isexec and 'x' or '') + (islink and 'l' or '') | |||
|
666 | repo.wwrite(gp.path, '', flags) | |||
|
667 | util.setflags(dst, islink, isexec) | |||
|
668 | addremove(repo, cfiles, similarity=similarity) | |||
|
669 | files = patches.keys() | |||
|
670 | files.extend([r for r in removes if r not in files]) | |||
|
671 | return sorted(files) | |||
|
672 | ||||
|
673 | def dirstatecopy(ui, repo, wctx, src, dst, dryrun=False, cwd=None): | |||
|
674 | """Update the dirstate to reflect the intent of copying src to dst. For | |||
|
675 | different reasons it might not end with dst being marked as copied from src. | |||
|
676 | """ | |||
|
677 | origsrc = repo.dirstate.copied(src) or src | |||
|
678 | if dst == origsrc: # copying back a copy? | |||
|
679 | if repo.dirstate[dst] not in 'mn' and not dryrun: | |||
|
680 | repo.dirstate.normallookup(dst) | |||
|
681 | else: | |||
|
682 | if repo.dirstate[origsrc] == 'a' and origsrc == src: | |||
|
683 | if not ui.quiet: | |||
|
684 | ui.warn(_("%s has not been committed yet, so no copy " | |||
|
685 | "data will be stored for %s.\n") | |||
|
686 | % (repo.pathto(origsrc, cwd), repo.pathto(dst, cwd))) | |||
|
687 | if repo.dirstate[dst] in '?r' and not dryrun: | |||
|
688 | wctx.add([dst]) | |||
|
689 | elif not dryrun: | |||
|
690 | wctx.copy(origsrc, dst) |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now