##// END OF EJS Templates
scmutil: fold in wdutil
Matt Mackall -
r14320:3438417a default
parent child Browse files
Show More
@@ -8,16 +8,16 b''
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, wdutil
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 = wdutil.expandpats
15 expandpats = scmutil.expandpats
16 match = wdutil.match
16 match = scmutil.match
17 matchall = wdutil.matchall
17 matchall = scmutil.matchall
18 matchfiles = wdutil.matchfiles
18 matchfiles = scmutil.matchfiles
19 addremove = wdutil.addremove
19 addremove = scmutil.addremove
20 dirstatecopy = wdutil.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 b''
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 b' 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