Show More
@@ -19,7 +19,7 b" def fetch(ui, repo, source='default', **" | |||
|
19 | 19 | merged, and the result of the merge is committed. Otherwise, the |
|
20 | 20 | working directory is updated.''' |
|
21 | 21 | |
|
22 | def postincoming(other, modheads): | |
|
22 | def postincoming(other, modheads, lock, wlock): | |
|
23 | 23 | if modheads == 0: |
|
24 | 24 | return 0 |
|
25 | 25 | if modheads == 1: |
@@ -50,7 +50,7 b" def fetch(ui, repo, source='default', **" | |||
|
50 | 50 | ui.status(_('new changeset %d:%s merges remote changes ' |
|
51 | 51 | 'with local\n') % (repo.changelog.rev(n), |
|
52 | 52 | short(n))) |
|
53 | def pull(): | |
|
53 | def pull(lock, wlock): | |
|
54 | 54 | cmdutil.setremoteconfig(ui, opts) |
|
55 | 55 | |
|
56 | 56 | other = hg.repository(ui, ui.expandpath(source)) |
@@ -61,7 +61,7 b" def fetch(ui, repo, source='default', **" | |||
|
61 | 61 | elif opts['rev']: |
|
62 | 62 | revs = [other.lookup(rev) for rev in opts['rev']] |
|
63 | 63 | modheads = repo.pull(other, heads=revs, lock=lock) |
|
64 | return postincoming(other, modheads) | |
|
64 | return postincoming(other, modheads, lock, wlock) | |
|
65 | 65 | |
|
66 | 66 | parent, p2 = repo.dirstate.parents() |
|
67 | 67 | if parent != repo.changelog.tip(): |
@@ -69,19 +69,19 b" def fetch(ui, repo, source='default', **" | |||
|
69 | 69 | '(use "hg update" to check out tip)')) |
|
70 | 70 | if p2 != nullid: |
|
71 | 71 | raise util.Abort(_('outstanding uncommitted merge')) |
|
72 |
wlock = |
|
|
73 | lock = repo.lock() | |
|
72 | wlock = lock = None | |
|
74 | 73 | try: |
|
74 | wlock = repo.wlock() | |
|
75 | lock = repo.lock() | |
|
75 | 76 | mod, add, rem = repo.status(wlock=wlock)[:3] |
|
76 | 77 | if mod or add or rem: |
|
77 | 78 | raise util.Abort(_('outstanding uncommitted changes')) |
|
78 | 79 | if len(repo.heads()) > 1: |
|
79 | 80 | raise util.Abort(_('multiple heads in this repository ' |
|
80 | 81 | '(use "hg heads" and "hg merge" to merge)')) |
|
81 | return pull() | |
|
82 | return pull(lock, wlock) | |
|
82 | 83 | finally: |
|
83 | lock.release() | |
|
84 | wlock.release() | |
|
84 | del lock, wlock | |
|
85 | 85 | |
|
86 | 86 | cmdtable = { |
|
87 | 87 | 'fetch': |
This diff has been collapsed as it changes many lines, (721 lines changed) Show them Hide them | |||
@@ -439,24 +439,28 b' class queue:' | |||
|
439 | 439 | def apply(self, repo, series, list=False, update_status=True, |
|
440 | 440 | strict=False, patchdir=None, merge=None, wlock=None, |
|
441 | 441 | all_files={}): |
|
442 | if not wlock: | |
|
443 | wlock = repo.wlock() | |
|
444 | lock = repo.lock() | |
|
445 | tr = repo.transaction() | |
|
442 | lock = tr = None | |
|
446 | 443 | try: |
|
447 | ret = self._apply(tr, repo, series, list, update_status, | |
|
448 | strict, patchdir, merge, wlock, | |
|
449 | lock=lock, all_files=all_files) | |
|
450 |
tr. |
|
|
451 | self.save_dirty() | |
|
452 | return ret | |
|
453 | except: | |
|
444 | if not wlock: | |
|
445 | wlock = repo.wlock() | |
|
446 | lock = repo.lock() | |
|
447 | tr = repo.transaction() | |
|
454 | 448 | try: |
|
455 | tr.abort() | |
|
456 | finally: | |
|
457 | repo.invalidate() | |
|
458 |
r |
|
|
459 | raise | |
|
449 | ret = self._apply(tr, repo, series, list, update_status, | |
|
450 | strict, patchdir, merge, wlock, | |
|
451 | lock=lock, all_files=all_files) | |
|
452 | tr.close() | |
|
453 | self.save_dirty() | |
|
454 | return ret | |
|
455 | except: | |
|
456 | try: | |
|
457 | tr.abort() | |
|
458 | finally: | |
|
459 | repo.invalidate() | |
|
460 | repo.dirstate.invalidate() | |
|
461 | raise | |
|
462 | finally: | |
|
463 | del lock, wlock, tr | |
|
460 | 464 | |
|
461 | 465 | def _apply(self, tr, repo, series, list=False, update_status=True, |
|
462 | 466 | strict=False, patchdir=None, merge=None, wlock=None, |
@@ -616,44 +620,51 b' class queue:' | |||
|
616 | 620 | commitfiles = m + a + r |
|
617 | 621 | self.check_toppatch(repo) |
|
618 | 622 | wlock = repo.wlock() |
|
619 | insert = self.full_series_end() | |
|
620 | if msg: | |
|
621 | n = repo.commit(commitfiles, msg, force=True, wlock=wlock) | |
|
622 | else: | |
|
623 | n = repo.commit(commitfiles, | |
|
624 | "[mq]: %s" % patch, force=True, wlock=wlock) | |
|
625 | if n == None: | |
|
626 | raise util.Abort(_("repo commit failed")) | |
|
627 | self.full_series[insert:insert] = [patch] | |
|
628 | self.applied.append(statusentry(revlog.hex(n), patch)) | |
|
629 | self.parse_series() | |
|
630 |
self.series |
|
|
631 |
self. |
|
|
632 | p = self.opener(patch, "w") | |
|
633 | if msg: | |
|
634 |
|
|
|
635 | p.write(msg) | |
|
636 | p.close() | |
|
637 | wlock = None | |
|
638 | r = self.qrepo() | |
|
639 | if r: r.add([patch]) | |
|
640 | if commitfiles: | |
|
641 | self.refresh(repo, short=True) | |
|
642 | self.removeundo(repo) | |
|
623 | try: | |
|
624 | insert = self.full_series_end() | |
|
625 | if msg: | |
|
626 | n = repo.commit(commitfiles, msg, force=True, wlock=wlock) | |
|
627 | else: | |
|
628 | n = repo.commit(commitfiles, | |
|
629 | "[mq]: %s" % patch, force=True, wlock=wlock) | |
|
630 | if n == None: | |
|
631 | raise util.Abort(_("repo commit failed")) | |
|
632 | self.full_series[insert:insert] = [patch] | |
|
633 | self.applied.append(statusentry(revlog.hex(n), patch)) | |
|
634 | self.parse_series() | |
|
635 | self.series_dirty = 1 | |
|
636 | self.applied_dirty = 1 | |
|
637 | p = self.opener(patch, "w") | |
|
638 | if msg: | |
|
639 | msg = msg + "\n" | |
|
640 | p.write(msg) | |
|
641 | p.close() | |
|
642 | wlock = None | |
|
643 | r = self.qrepo() | |
|
644 | if r: r.add([patch]) | |
|
645 | if commitfiles: | |
|
646 | self.refresh(repo, short=True) | |
|
647 | self.removeundo(repo) | |
|
648 | finally: | |
|
649 | del wlock | |
|
643 | 650 | |
|
644 | 651 | def strip(self, repo, rev, update=True, backup="all", wlock=None): |
|
645 |
|
|
|
646 | wlock = repo.wlock() | |
|
647 | lock = repo.lock() | |
|
652 | lock = None | |
|
653 | try: | |
|
654 | if not wlock: | |
|
655 | wlock = repo.wlock() | |
|
656 | lock = repo.lock() | |
|
648 | 657 | |
|
649 | if update: | |
|
650 | self.check_localchanges(repo, refresh=False) | |
|
651 | urev = self.qparents(repo, rev) | |
|
652 | hg.clean(repo, urev, wlock=wlock) | |
|
653 | repo.dirstate.write() | |
|
658 | if update: | |
|
659 | self.check_localchanges(repo, refresh=False) | |
|
660 | urev = self.qparents(repo, rev) | |
|
661 | hg.clean(repo, urev, wlock=wlock) | |
|
662 | repo.dirstate.write() | |
|
654 | 663 | |
|
655 | self.removeundo(repo) | |
|
656 | repair.strip(self.ui, repo, rev, backup) | |
|
664 | self.removeundo(repo) | |
|
665 | repair.strip(self.ui, repo, rev, backup) | |
|
666 | finally: | |
|
667 | del lock, wlock | |
|
657 | 668 | |
|
658 | 669 | def isapplied(self, patch): |
|
659 | 670 | """returns (index, rev, patch)""" |
@@ -740,69 +751,74 b' class queue:' | |||
|
740 | 751 | mergeq=None, wlock=None): |
|
741 | 752 | if not wlock: |
|
742 | 753 | wlock = repo.wlock() |
|
743 | patch = self.lookup(patch) | |
|
744 | # Suppose our series file is: A B C and the current 'top' patch is B. | |
|
745 | # qpush C should be performed (moving forward) | |
|
746 | # qpush B is a NOP (no change) | |
|
747 | # qpush A is an error (can't go backwards with qpush) | |
|
748 | if patch: | |
|
749 |
i |
|
|
750 | if info: | |
|
751 |
if info |
|
|
752 | raise util.Abort(_("cannot push to a previous patch: %s") % | |
|
753 |
|
|
|
754 | if info[0] < len(self.series) - 1: | |
|
755 | self.ui.warn(_('qpush: %s is already at the top\n') % patch) | |
|
756 |
|
|
|
757 | self.ui.warn(_('all patches are currently applied\n')) | |
|
758 |
|
|
|
754 | try: | |
|
755 | patch = self.lookup(patch) | |
|
756 | # Suppose our series file is: A B C and the current 'top' | |
|
757 | # patch is B. qpush C should be performed (moving forward) | |
|
758 | # qpush B is a NOP (no change) qpush A is an error (can't | |
|
759 | # go backwards with qpush) | |
|
760 | if patch: | |
|
761 | info = self.isapplied(patch) | |
|
762 | if info: | |
|
763 | if info[0] < len(self.applied) - 1: | |
|
764 | raise util.Abort( | |
|
765 | _("cannot push to a previous patch: %s") % patch) | |
|
766 | if info[0] < len(self.series) - 1: | |
|
767 | self.ui.warn( | |
|
768 | _('qpush: %s is already at the top\n') % patch) | |
|
769 | else: | |
|
770 | self.ui.warn(_('all patches are currently applied\n')) | |
|
771 | return | |
|
759 | 772 | |
|
760 | # Following the above example, starting at 'top' of B: | |
|
761 |
|
|
|
762 |
# an argument is an error (nothing to |
|
|
763 | # of "...while hg qpush..." to work as it detects an error when done | |
|
764 | if self.series_end() == len(self.series): | |
|
765 | self.ui.warn(_('patch series already fully applied\n')) | |
|
766 | return 1 | |
|
767 | if not force: | |
|
768 | self.check_localchanges(repo) | |
|
773 | # Following the above example, starting at 'top' of B: | |
|
774 | # qpush should be performed (pushes C), but a subsequent | |
|
775 | # qpush without an argument is an error (nothing to | |
|
776 | # apply). This allows a loop of "...while hg qpush..." to | |
|
777 | # work as it detects an error when done | |
|
778 | if self.series_end() == len(self.series): | |
|
779 | self.ui.warn(_('patch series already fully applied\n')) | |
|
780 | return 1 | |
|
781 | if not force: | |
|
782 | self.check_localchanges(repo) | |
|
769 | 783 | |
|
770 | self.applied_dirty = 1; | |
|
771 | start = self.series_end() | |
|
772 | if start > 0: | |
|
773 | self.check_toppatch(repo) | |
|
774 | if not patch: | |
|
775 | patch = self.series[start] | |
|
776 | end = start + 1 | |
|
777 | else: | |
|
778 | end = self.series.index(patch, start) + 1 | |
|
779 | s = self.series[start:end] | |
|
780 | all_files = {} | |
|
781 | try: | |
|
782 | if mergeq: | |
|
783 | ret = self.mergepatch(repo, mergeq, s, wlock) | |
|
784 | self.applied_dirty = 1; | |
|
785 | start = self.series_end() | |
|
786 | if start > 0: | |
|
787 | self.check_toppatch(repo) | |
|
788 | if not patch: | |
|
789 | patch = self.series[start] | |
|
790 | end = start + 1 | |
|
784 | 791 | else: |
|
785 | ret = self.apply(repo, s, list, wlock=wlock, | |
|
786 | all_files=all_files) | |
|
787 | except: | |
|
788 | self.ui.warn(_('cleaning up working directory...')) | |
|
789 | node = repo.dirstate.parents()[0] | |
|
790 |
|
|
|
791 | unknown = repo.status(wlock=wlock)[4] | |
|
792 | # only remove unknown files that we know we touched or | |
|
793 | # created while patching | |
|
794 | for f in unknown: | |
|
795 | if f in all_files: | |
|
796 | util.unlink(repo.wjoin(f)) | |
|
797 | self.ui.warn(_('done\n')) | |
|
798 | raise | |
|
799 | top = self.applied[-1].name | |
|
800 | if ret[0]: | |
|
801 | self.ui.write("Errors during apply, please fix and refresh %s\n" % | |
|
802 |
|
|
|
803 | else: | |
|
804 | self.ui.write("Now at: %s\n" % top) | |
|
805 | return ret[0] | |
|
792 | end = self.series.index(patch, start) + 1 | |
|
793 | s = self.series[start:end] | |
|
794 | all_files = {} | |
|
795 | try: | |
|
796 | if mergeq: | |
|
797 | ret = self.mergepatch(repo, mergeq, s, wlock) | |
|
798 | else: | |
|
799 | ret = self.apply(repo, s, list, wlock=wlock, | |
|
800 | all_files=all_files) | |
|
801 | except: | |
|
802 | self.ui.warn(_('cleaning up working directory...')) | |
|
803 | node = repo.dirstate.parents()[0] | |
|
804 | hg.revert(repo, node, None, wlock) | |
|
805 | unknown = repo.status(wlock=wlock)[4] | |
|
806 | # only remove unknown files that we know we touched or | |
|
807 | # created while patching | |
|
808 | for f in unknown: | |
|
809 | if f in all_files: | |
|
810 | util.unlink(repo.wjoin(f)) | |
|
811 | self.ui.warn(_('done\n')) | |
|
812 | raise | |
|
813 | top = self.applied[-1].name | |
|
814 | if ret[0]: | |
|
815 | self.ui.write( | |
|
816 | "Errors during apply, please fix and refresh %s\n" % top) | |
|
817 | else: | |
|
818 | self.ui.write("Now at: %s\n" % top) | |
|
819 | return ret[0] | |
|
820 | finally: | |
|
821 | del wlock | |
|
806 | 822 | |
|
807 | 823 | def pop(self, repo, patch=None, force=False, update=True, all=False, |
|
808 | 824 | wlock=None): |
@@ -812,82 +828,85 b' class queue:' | |||
|
812 | 828 | |
|
813 | 829 | if not wlock: |
|
814 | 830 | wlock = repo.wlock() |
|
815 |
|
|
|
816 |
|
|
|
817 | info = self.isapplied(patch) | |
|
818 | if not info: | |
|
819 | patch = self.lookup(patch) | |
|
820 |
|
|
|
821 | if not info: | |
|
822 | raise util.Abort(_("patch %s is not applied") % patch) | |
|
831 | try: | |
|
832 | if patch: | |
|
833 | # index, rev, patch | |
|
834 | info = self.isapplied(patch) | |
|
835 | if not info: | |
|
836 | patch = self.lookup(patch) | |
|
837 | info = self.isapplied(patch) | |
|
838 | if not info: | |
|
839 | raise util.Abort(_("patch %s is not applied") % patch) | |
|
823 | 840 | |
|
824 | if len(self.applied) == 0: | |
|
825 | # Allow qpop -a to work repeatedly, | |
|
826 | # but not qpop without an argument | |
|
827 | self.ui.warn(_("no patches applied\n")) | |
|
828 | return not all | |
|
841 | if len(self.applied) == 0: | |
|
842 | # Allow qpop -a to work repeatedly, | |
|
843 | # but not qpop without an argument | |
|
844 | self.ui.warn(_("no patches applied\n")) | |
|
845 | return not all | |
|
829 | 846 | |
|
830 | if not update: | |
|
831 | parents = repo.dirstate.parents() | |
|
832 | rr = [ revlog.bin(x.rev) for x in self.applied ] | |
|
833 | for p in parents: | |
|
834 | if p in rr: | |
|
835 | self.ui.warn("qpop: forcing dirstate update\n") | |
|
836 | update = True | |
|
847 | if not update: | |
|
848 | parents = repo.dirstate.parents() | |
|
849 | rr = [ revlog.bin(x.rev) for x in self.applied ] | |
|
850 | for p in parents: | |
|
851 | if p in rr: | |
|
852 | self.ui.warn("qpop: forcing dirstate update\n") | |
|
853 | update = True | |
|
837 | 854 | |
|
838 | if not force and update: | |
|
839 | self.check_localchanges(repo) | |
|
855 | if not force and update: | |
|
856 | self.check_localchanges(repo) | |
|
840 | 857 | |
|
841 | self.applied_dirty = 1; | |
|
842 | end = len(self.applied) | |
|
843 | if not patch: | |
|
844 | if all: | |
|
845 | popi = 0 | |
|
858 | self.applied_dirty = 1; | |
|
859 | end = len(self.applied) | |
|
860 | if not patch: | |
|
861 | if all: | |
|
862 | popi = 0 | |
|
863 | else: | |
|
864 | popi = len(self.applied) - 1 | |
|
846 | 865 | else: |
|
847 |
popi = |
|
|
848 | else: | |
|
849 | popi = info[0] + 1 | |
|
850 |
|
|
|
851 | self.ui.warn("qpop: %s is already at the top\n" % patch) | |
|
852 | return | |
|
853 | info = [ popi ] + [self.applied[popi].rev, self.applied[popi].name] | |
|
866 | popi = info[0] + 1 | |
|
867 | if popi >= end: | |
|
868 | self.ui.warn("qpop: %s is already at the top\n" % patch) | |
|
869 | return | |
|
870 | info = [ popi ] + [self.applied[popi].rev, self.applied[popi].name] | |
|
854 | 871 | |
|
855 | start = info[0] | |
|
856 | rev = revlog.bin(info[1]) | |
|
872 | start = info[0] | |
|
873 | rev = revlog.bin(info[1]) | |
|
857 | 874 | |
|
858 | # we know there are no local changes, so we can make a simplified | |
|
859 | # form of hg.update. | |
|
860 | if update: | |
|
861 | top = self.check_toppatch(repo) | |
|
862 | qp = self.qparents(repo, rev) | |
|
863 | changes = repo.changelog.read(qp) | |
|
864 | mmap = repo.manifest.read(changes[0]) | |
|
865 | m, a, r, d, u = repo.status(qp, top)[:5] | |
|
866 | if d: | |
|
867 | raise util.Abort("deletions found between repo revs") | |
|
868 | for f in m: | |
|
869 | getfile(f, mmap[f]) | |
|
870 | for f in r: | |
|
871 | getfile(f, mmap[f]) | |
|
872 | util.set_exec(repo.wjoin(f), mmap.execf(f)) | |
|
873 | for f in m + r: | |
|
874 | repo.dirstate.normal(f) | |
|
875 | for f in a: | |
|
876 | try: | |
|
877 | os.unlink(repo.wjoin(f)) | |
|
878 | except OSError, e: | |
|
879 | if e.errno != errno.ENOENT: | |
|
880 | raise | |
|
881 | try: os.removedirs(os.path.dirname(repo.wjoin(f))) | |
|
882 | except: pass | |
|
883 | repo.dirstate.forget(f) | |
|
884 | repo.dirstate.setparents(qp, revlog.nullid) | |
|
885 | self.strip(repo, rev, update=False, backup='strip', wlock=wlock) | |
|
886 | del self.applied[start:end] | |
|
887 | if len(self.applied): | |
|
888 | self.ui.write("Now at: %s\n" % self.applied[-1].name) | |
|
889 | else: | |
|
890 | self.ui.write("Patch queue now empty\n") | |
|
875 | # we know there are no local changes, so we can make a simplified | |
|
876 | # form of hg.update. | |
|
877 | if update: | |
|
878 | top = self.check_toppatch(repo) | |
|
879 | qp = self.qparents(repo, rev) | |
|
880 | changes = repo.changelog.read(qp) | |
|
881 | mmap = repo.manifest.read(changes[0]) | |
|
882 | m, a, r, d, u = repo.status(qp, top)[:5] | |
|
883 | if d: | |
|
884 | raise util.Abort("deletions found between repo revs") | |
|
885 | for f in m: | |
|
886 | getfile(f, mmap[f]) | |
|
887 | for f in r: | |
|
888 | getfile(f, mmap[f]) | |
|
889 | util.set_exec(repo.wjoin(f), mmap.execf(f)) | |
|
890 | for f in m + r: | |
|
891 | repo.dirstate.normal(f) | |
|
892 | for f in a: | |
|
893 | try: | |
|
894 | os.unlink(repo.wjoin(f)) | |
|
895 | except OSError, e: | |
|
896 | if e.errno != errno.ENOENT: | |
|
897 | raise | |
|
898 | try: os.removedirs(os.path.dirname(repo.wjoin(f))) | |
|
899 | except: pass | |
|
900 | repo.dirstate.forget(f) | |
|
901 | repo.dirstate.setparents(qp, revlog.nullid) | |
|
902 | self.strip(repo, rev, update=False, backup='strip', wlock=wlock) | |
|
903 | del self.applied[start:end] | |
|
904 | if len(self.applied): | |
|
905 | self.ui.write("Now at: %s\n" % self.applied[-1].name) | |
|
906 | else: | |
|
907 | self.ui.write("Patch queue now empty\n") | |
|
908 | finally: | |
|
909 | del wlock | |
|
891 | 910 | |
|
892 | 911 | def diff(self, repo, pats, opts): |
|
893 | 912 | top = self.check_toppatch(repo) |
@@ -904,179 +923,184 b' class queue:' | |||
|
904 | 923 | self.ui.write("No patches applied\n") |
|
905 | 924 | return 1 |
|
906 | 925 | wlock = repo.wlock() |
|
907 | self.check_toppatch(repo) | |
|
908 | (top, patchfn) = (self.applied[-1].rev, self.applied[-1].name) | |
|
909 | top = revlog.bin(top) | |
|
910 |
|
|
|
911 |
|
|
|
912 | message, comments, user, date, patchfound = self.readheaders(patchfn) | |
|
913 | ||
|
914 | patchf = self.opener(patchfn, 'r+') | |
|
915 | ||
|
916 | # if the patch was a git patch, refresh it as a git patch | |
|
917 | for line in patchf: | |
|
918 | if line.startswith('diff --git'): | |
|
919 | self.diffopts().git = True | |
|
920 | break | |
|
921 | patchf.seek(0) | |
|
922 | patchf.truncate() | |
|
926 | try: | |
|
927 | self.check_toppatch(repo) | |
|
928 | (top, patchfn) = (self.applied[-1].rev, self.applied[-1].name) | |
|
929 | top = revlog.bin(top) | |
|
930 | cparents = repo.changelog.parents(top) | |
|
931 | patchparent = self.qparents(repo, top) | |
|
932 | message, comments, user, date, patchfound = self.readheaders(patchfn) | |
|
923 | 933 | |
|
924 | msg = opts.get('msg', '').rstrip() | |
|
925 | if msg: | |
|
926 | if comments: | |
|
927 | # Remove existing message. | |
|
928 | ci = 0 | |
|
929 | subj = None | |
|
930 | for mi in xrange(len(message)): | |
|
931 | if comments[ci].lower().startswith('subject: '): | |
|
932 | subj = comments[ci][9:] | |
|
933 | while message[mi] != comments[ci] and message[mi] != subj: | |
|
934 | ci += 1 | |
|
935 | del comments[ci] | |
|
936 | comments.append(msg) | |
|
937 | if comments: | |
|
938 | comments = "\n".join(comments) + '\n\n' | |
|
939 | patchf.write(comments) | |
|
934 | patchf = self.opener(patchfn, 'r+') | |
|
935 | ||
|
936 | # if the patch was a git patch, refresh it as a git patch | |
|
937 | for line in patchf: | |
|
938 | if line.startswith('diff --git'): | |
|
939 | self.diffopts().git = True | |
|
940 | break | |
|
941 | patchf.seek(0) | |
|
942 | patchf.truncate() | |
|
940 | 943 | |
|
941 |
|
|
|
942 | self.diffopts().git = True | |
|
943 | fns, matchfn, anypats = cmdutil.matchpats(repo, pats, opts) | |
|
944 | tip = repo.changelog.tip() | |
|
945 | if top == tip: | |
|
946 | # if the top of our patch queue is also the tip, there is an | |
|
947 | # optimization here. We update the dirstate in place and strip | |
|
948 | # off the tip commit. Then just commit the current directory | |
|
949 | # tree. We can also send repo.commit the list of files | |
|
950 | # changed to speed up the diff | |
|
951 | # | |
|
952 | # in short mode, we only diff the files included in the | |
|
953 | # patch already | |
|
954 |
|
|
|
955 | # this should really read: | |
|
956 | # mm, dd, aa, aa2, uu = repo.status(tip, patchparent)[:5] | |
|
957 | # but we do it backwards to take advantage of manifest/chlog | |
|
958 | # caching against the next repo.status call | |
|
959 | # | |
|
960 | mm, aa, dd, aa2, uu = repo.status(patchparent, tip)[:5] | |
|
961 | changes = repo.changelog.read(tip) | |
|
962 | man = repo.manifest.read(changes[0]) | |
|
963 | aaa = aa[:] | |
|
964 | if opts.get('short'): | |
|
965 | filelist = mm + aa + dd | |
|
966 | match = dict.fromkeys(filelist).__contains__ | |
|
967 | else: | |
|
968 | filelist = None | |
|
969 | match = util.always | |
|
970 | m, a, r, d, u = repo.status(files=filelist, match=match)[:5] | |
|
944 | msg = opts.get('msg', '').rstrip() | |
|
945 | if msg: | |
|
946 | if comments: | |
|
947 | # Remove existing message. | |
|
948 | ci = 0 | |
|
949 | subj = None | |
|
950 | for mi in xrange(len(message)): | |
|
951 | if comments[ci].lower().startswith('subject: '): | |
|
952 | subj = comments[ci][9:] | |
|
953 | while message[mi] != comments[ci] and message[mi] != subj: | |
|
954 | ci += 1 | |
|
955 | del comments[ci] | |
|
956 | comments.append(msg) | |
|
957 | if comments: | |
|
958 | comments = "\n".join(comments) + '\n\n' | |
|
959 | patchf.write(comments) | |
|
971 | 960 | |
|
972 | # we might end up with files that were added between tip and | |
|
973 | # the dirstate parent, but then changed in the local dirstate. | |
|
974 | # in this case, we want them to only show up in the added section | |
|
975 | for x in m: | |
|
976 |
|
|
|
977 | mm.append(x) | |
|
978 | # we might end up with files added by the local dirstate that | |
|
979 | # were deleted by the patch. In this case, they should only | |
|
980 | # show up in the changed section. | |
|
981 | for x in a: | |
|
982 |
|
|
|
983 | del dd[dd.index(x)] | |
|
984 |
|
|
|
961 | if opts.get('git'): | |
|
962 | self.diffopts().git = True | |
|
963 | fns, matchfn, anypats = cmdutil.matchpats(repo, pats, opts) | |
|
964 | tip = repo.changelog.tip() | |
|
965 | if top == tip: | |
|
966 | # if the top of our patch queue is also the tip, there is an | |
|
967 | # optimization here. We update the dirstate in place and strip | |
|
968 | # off the tip commit. Then just commit the current directory | |
|
969 | # tree. We can also send repo.commit the list of files | |
|
970 | # changed to speed up the diff | |
|
971 | # | |
|
972 | # in short mode, we only diff the files included in the | |
|
973 | # patch already | |
|
974 | # | |
|
975 | # this should really read: | |
|
976 | # mm, dd, aa, aa2, uu = repo.status(tip, patchparent)[:5] | |
|
977 | # but we do it backwards to take advantage of manifest/chlog | |
|
978 | # caching against the next repo.status call | |
|
979 | # | |
|
980 | mm, aa, dd, aa2, uu = repo.status(patchparent, tip)[:5] | |
|
981 | changes = repo.changelog.read(tip) | |
|
982 | man = repo.manifest.read(changes[0]) | |
|
983 | aaa = aa[:] | |
|
984 | if opts.get('short'): | |
|
985 | filelist = mm + aa + dd | |
|
986 | match = dict.fromkeys(filelist).__contains__ | |
|
985 | 987 | else: |
|
986 |
|
|
|
987 | # make sure any files deleted in the local dirstate | |
|
988 | # are not in the add or change column of the patch | |
|
989 | forget = [] | |
|
990 | for x in d + r: | |
|
991 | if x in aa: | |
|
992 | del aa[aa.index(x)] | |
|
993 | forget.append(x) | |
|
994 | continue | |
|
995 | elif x in mm: | |
|
996 | del mm[mm.index(x)] | |
|
997 | dd.append(x) | |
|
988 | filelist = None | |
|
989 | match = util.always | |
|
990 | m, a, r, d, u = repo.status(files=filelist, match=match)[:5] | |
|
998 | 991 | |
|
999 | m = util.unique(mm) | |
|
1000 | r = util.unique(dd) | |
|
1001 | a = util.unique(aa) | |
|
1002 | c = [filter(matchfn, l) for l in (m, a, r, [], u)] | |
|
1003 | filelist = util.unique(c[0] + c[1] + c[2]) | |
|
1004 | patch.diff(repo, patchparent, files=filelist, match=matchfn, | |
|
1005 | fp=patchf, changes=c, opts=self.diffopts()) | |
|
1006 | patchf.close() | |
|
992 | # we might end up with files that were added between | |
|
993 | # tip and the dirstate parent, but then changed in the | |
|
994 | # local dirstate. in this case, we want them to only | |
|
995 | # show up in the added section | |
|
996 | for x in m: | |
|
997 | if x not in aa: | |
|
998 | mm.append(x) | |
|
999 | # we might end up with files added by the local dirstate that | |
|
1000 | # were deleted by the patch. In this case, they should only | |
|
1001 | # show up in the changed section. | |
|
1002 | for x in a: | |
|
1003 | if x in dd: | |
|
1004 | del dd[dd.index(x)] | |
|
1005 | mm.append(x) | |
|
1006 | else: | |
|
1007 | aa.append(x) | |
|
1008 | # make sure any files deleted in the local dirstate | |
|
1009 | # are not in the add or change column of the patch | |
|
1010 | forget = [] | |
|
1011 | for x in d + r: | |
|
1012 | if x in aa: | |
|
1013 | del aa[aa.index(x)] | |
|
1014 | forget.append(x) | |
|
1015 | continue | |
|
1016 | elif x in mm: | |
|
1017 | del mm[mm.index(x)] | |
|
1018 | dd.append(x) | |
|
1019 | ||
|
1020 | m = util.unique(mm) | |
|
1021 | r = util.unique(dd) | |
|
1022 | a = util.unique(aa) | |
|
1023 | c = [filter(matchfn, l) for l in (m, a, r, [], u)] | |
|
1024 | filelist = util.unique(c[0] + c[1] + c[2]) | |
|
1025 | patch.diff(repo, patchparent, files=filelist, match=matchfn, | |
|
1026 | fp=patchf, changes=c, opts=self.diffopts()) | |
|
1027 | patchf.close() | |
|
1007 | 1028 | |
|
1008 | repo.dirstate.setparents(*cparents) | |
|
1009 | copies = {} | |
|
1010 | for dst in a: | |
|
1011 | src = repo.dirstate.copied(dst) | |
|
1012 | if src is None: | |
|
1013 | continue | |
|
1014 | copies.setdefault(src, []).append(dst) | |
|
1015 | repo.dirstate.add(dst) | |
|
1016 | # remember the copies between patchparent and tip | |
|
1017 | # this may be slow, so don't do it if we're not tracking copies | |
|
1018 | if self.diffopts().git: | |
|
1019 | for dst in aaa: | |
|
1020 | f = repo.file(dst) | |
|
1021 | src = f.renamed(man[dst]) | |
|
1022 | if src: | |
|
1023 | copies[src[0]] = copies.get(dst, []) | |
|
1024 | if dst in a: | |
|
1025 | copies[src[0]].append(dst) | |
|
1026 | # we can't copy a file created by the patch itself | |
|
1027 | if dst in copies: | |
|
1028 | del copies[dst] | |
|
1029 | for src, dsts in copies.iteritems(): | |
|
1030 | for dst in dsts: | |
|
1031 | repo.dirstate.copy(src, dst) | |
|
1032 | for f in r: | |
|
1033 | repo.dirstate.remove(f) | |
|
1034 |
# if the patch excludes a modified file, mark that |
|
|
1035 | # so status can see it. | |
|
1036 | mm = [] | |
|
1037 | for i in xrange(len(m)-1, -1, -1): | |
|
1038 | if not matchfn(m[i]): | |
|
1039 | mm.append(m[i]) | |
|
1040 | del m[i] | |
|
1041 | for f in m: | |
|
1042 | repo.dirstate.normal(f) | |
|
1043 | for f in mm: | |
|
1044 | repo.dirstate.normaldirty(f) | |
|
1045 | for f in forget: | |
|
1046 | repo.dirstate.forget(f) | |
|
1029 | repo.dirstate.setparents(*cparents) | |
|
1030 | copies = {} | |
|
1031 | for dst in a: | |
|
1032 | src = repo.dirstate.copied(dst) | |
|
1033 | if src is None: | |
|
1034 | continue | |
|
1035 | copies.setdefault(src, []).append(dst) | |
|
1036 | repo.dirstate.add(dst) | |
|
1037 | # remember the copies between patchparent and tip | |
|
1038 | # this may be slow, so don't do it if we're not tracking copies | |
|
1039 | if self.diffopts().git: | |
|
1040 | for dst in aaa: | |
|
1041 | f = repo.file(dst) | |
|
1042 | src = f.renamed(man[dst]) | |
|
1043 | if src: | |
|
1044 | copies[src[0]] = copies.get(dst, []) | |
|
1045 | if dst in a: | |
|
1046 | copies[src[0]].append(dst) | |
|
1047 | # we can't copy a file created by the patch itself | |
|
1048 | if dst in copies: | |
|
1049 | del copies[dst] | |
|
1050 | for src, dsts in copies.iteritems(): | |
|
1051 | for dst in dsts: | |
|
1052 | repo.dirstate.copy(src, dst) | |
|
1053 | for f in r: | |
|
1054 | repo.dirstate.remove(f) | |
|
1055 | # if the patch excludes a modified file, mark that | |
|
1056 | # file with mtime=0 so status can see it. | |
|
1057 | mm = [] | |
|
1058 | for i in xrange(len(m)-1, -1, -1): | |
|
1059 | if not matchfn(m[i]): | |
|
1060 | mm.append(m[i]) | |
|
1061 | del m[i] | |
|
1062 | for f in m: | |
|
1063 | repo.dirstate.normal(f) | |
|
1064 | for f in mm: | |
|
1065 | repo.dirstate.normaldirty(f) | |
|
1066 | for f in forget: | |
|
1067 | repo.dirstate.forget(f) | |
|
1047 | 1068 | |
|
1048 | if not msg: | |
|
1049 | if not message: | |
|
1050 | message = "[mq]: %s\n" % patchfn | |
|
1069 | if not msg: | |
|
1070 | if not message: | |
|
1071 | message = "[mq]: %s\n" % patchfn | |
|
1072 | else: | |
|
1073 | message = "\n".join(message) | |
|
1051 | 1074 | else: |
|
1052 |
message = |
|
|
1053 | else: | |
|
1054 | message = msg | |
|
1075 | message = msg | |
|
1055 | 1076 | |
|
1056 |
self.strip(repo, top, update=False, |
|
|
1057 | n = repo.commit(filelist, message, changes[1], match=matchfn, | |
|
1058 | force=1, wlock=wlock) | |
|
1059 | self.applied[-1] = statusentry(revlog.hex(n), patchfn) | |
|
1060 | self.applied_dirty = 1 | |
|
1061 | self.removeundo(repo) | |
|
1062 | else: | |
|
1063 | self.printdiff(repo, patchparent, fp=patchf) | |
|
1064 | patchf.close() | |
|
1065 |
|
|
|
1066 | for a in added: | |
|
1067 |
f |
|
|
1068 | try: | |
|
1069 |
|
|
|
1070 | except OSError, e: | |
|
1071 | if e.errno != errno.ENOENT: | |
|
1072 |
|
|
|
1073 | try: os.removedirs(os.path.dirname(f)) | |
|
1074 | except: pass | |
|
1075 | # forget the file copies in the dirstate | |
|
1076 |
|
|
|
1077 | repo.dirstate.forget(a) | |
|
1078 | self.pop(repo, force=True, wlock=wlock) | |
|
1079 |
self.p |
|
|
1077 | self.strip(repo, top, update=False, | |
|
1078 | backup='strip', wlock=wlock) | |
|
1079 | n = repo.commit(filelist, message, changes[1], match=matchfn, | |
|
1080 | force=1, wlock=wlock) | |
|
1081 | self.applied[-1] = statusentry(revlog.hex(n), patchfn) | |
|
1082 | self.applied_dirty = 1 | |
|
1083 | self.removeundo(repo) | |
|
1084 | else: | |
|
1085 | self.printdiff(repo, patchparent, fp=patchf) | |
|
1086 | patchf.close() | |
|
1087 | added = repo.status()[1] | |
|
1088 | for a in added: | |
|
1089 | f = repo.wjoin(a) | |
|
1090 | try: | |
|
1091 | os.unlink(f) | |
|
1092 | except OSError, e: | |
|
1093 | if e.errno != errno.ENOENT: | |
|
1094 | raise | |
|
1095 | try: os.removedirs(os.path.dirname(f)) | |
|
1096 | except: pass | |
|
1097 | # forget the file copies in the dirstate | |
|
1098 | # push should readd the files later on | |
|
1099 | repo.dirstate.forget(a) | |
|
1100 | self.pop(repo, force=True, wlock=wlock) | |
|
1101 | self.push(repo, force=True, wlock=wlock) | |
|
1102 | finally: | |
|
1103 | del wlock | |
|
1080 | 1104 | |
|
1081 | 1105 | def init(self, repo, create=False): |
|
1082 | 1106 | if not create and os.path.isdir(self.path): |
@@ -1872,10 +1896,13 b' def rename(ui, repo, patch, name=None, *' | |||
|
1872 | 1896 | r = q.qrepo() |
|
1873 | 1897 | if r: |
|
1874 | 1898 | wlock = r.wlock() |
|
1875 | if r.dirstate[name] == 'r': | |
|
1876 |
r. |
|
|
1877 |
r. |
|
|
1878 |
r. |
|
|
1899 | try: | |
|
1900 | if r.dirstate[name] == 'r': | |
|
1901 | r.undelete([name], wlock) | |
|
1902 | r.copy(patch, name, wlock) | |
|
1903 | r.remove([patch], False, wlock) | |
|
1904 | finally: | |
|
1905 | del wlock | |
|
1879 | 1906 | |
|
1880 | 1907 | q.save_dirty() |
|
1881 | 1908 |
@@ -96,9 +96,10 b' class transplanter:' | |||
|
96 | 96 | diffopts = patch.diffopts(self.ui, opts) |
|
97 | 97 | diffopts.git = True |
|
98 | 98 | |
|
99 |
wlock = |
|
|
100 | lock = repo.lock() | |
|
99 | lock = wlock = None | |
|
101 | 100 | try: |
|
101 | wlock = repo.wlock() | |
|
102 | lock = repo.lock() | |
|
102 | 103 | for rev in revs: |
|
103 | 104 | node = revmap[rev] |
|
104 | 105 | revstr = '%s:%s' % (rev, revlog.short(node)) |
@@ -166,6 +167,7 b' class transplanter:' | |||
|
166 | 167 | finally: |
|
167 | 168 | self.saveseries(revmap, merges) |
|
168 | 169 | self.transplants.write() |
|
170 | del lock, wlock | |
|
169 | 171 | |
|
170 | 172 | def filter(self, filter, changelog, patchfile): |
|
171 | 173 | '''arbitrarily rewrite changeset before applying it''' |
@@ -272,20 +274,25 b' class transplanter:' | |||
|
272 | 274 | |
|
273 | 275 | extra = {'transplant_source': node} |
|
274 | 276 | wlock = repo.wlock() |
|
275 | p1, p2 = repo.dirstate.parents() | |
|
276 | if p1 != parents[0]: | |
|
277 | raise util.Abort(_('working dir not at transplant parent %s') % | |
|
278 | revlog.hex(parents[0])) | |
|
279 | if merge: | |
|
280 | repo.dirstate.setparents(p1, parents[1]) | |
|
281 | n = repo.commit(None, message, user, date, wlock=wlock, extra=extra) | |
|
282 | if not n: | |
|
283 | raise util.Abort(_('commit failed')) | |
|
284 | if not merge: | |
|
285 | self.transplants.set(n, node) | |
|
286 | self.unlog() | |
|
277 | try: | |
|
278 | p1, p2 = repo.dirstate.parents() | |
|
279 | if p1 != parents[0]: | |
|
280 | raise util.Abort( | |
|
281 | _('working dir not at transplant parent %s') % | |
|
282 | revlog.hex(parents[0])) | |
|
283 | if merge: | |
|
284 | repo.dirstate.setparents(p1, parents[1]) | |
|
285 | n = repo.commit(None, message, user, date, wlock=wlock, | |
|
286 | extra=extra) | |
|
287 | if not n: | |
|
288 | raise util.Abort(_('commit failed')) | |
|
289 | if not merge: | |
|
290 | self.transplants.set(n, node) | |
|
291 | self.unlog() | |
|
287 | 292 | |
|
288 | return n, node | |
|
293 | return n, node | |
|
294 | finally: | |
|
295 | del wlock | |
|
289 | 296 | |
|
290 | 297 | def readseries(self): |
|
291 | 298 | nodes = [] |
@@ -676,7 +676,10 b' def copy(ui, repo, *pats, **opts):' | |||
|
676 | 676 | before that, see hg revert. |
|
677 | 677 | """ |
|
678 | 678 | wlock = repo.wlock(False) |
|
679 | errs, copied = docopy(ui, repo, pats, opts, wlock) | |
|
679 | try: | |
|
680 | errs, copied = docopy(ui, repo, pats, opts, wlock) | |
|
681 | finally: | |
|
682 | del wlock | |
|
680 | 683 | return errs |
|
681 | 684 | |
|
682 | 685 | def debugancestor(ui, index, rev1, rev2): |
@@ -713,7 +716,10 b' def debugrebuildstate(ui, repo, rev=""):' | |||
|
713 | 716 | ctx = repo.changectx(rev) |
|
714 | 717 | files = ctx.manifest() |
|
715 | 718 | wlock = repo.wlock() |
|
716 | repo.dirstate.rebuild(rev, files) | |
|
719 | try: | |
|
720 | repo.dirstate.rebuild(rev, files) | |
|
721 | finally: | |
|
722 | del wlock | |
|
717 | 723 | |
|
718 | 724 | def debugcheckstate(ui, repo): |
|
719 | 725 | """validate the correctness of the current dirstate""" |
@@ -782,7 +788,7 b' def debugsetparents(ui, repo, rev1, rev2' | |||
|
782 | 788 | try: |
|
783 | 789 | repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2)) |
|
784 | 790 | finally: |
|
785 |
wlock |
|
|
791 | del wlock | |
|
786 | 792 | |
|
787 | 793 | def debugstate(ui, repo): |
|
788 | 794 | """show the contents of the current dirstate""" |
@@ -1581,70 +1587,76 b' def import_(ui, repo, patch1, *patches, ' | |||
|
1581 | 1587 | |
|
1582 | 1588 | d = opts["base"] |
|
1583 | 1589 | strip = opts["strip"] |
|
1584 | ||
|
1585 | wlock = repo.wlock() | |
|
1586 | lock = repo.lock() | |
|
1587 | ||
|
1588 | for p in patches: | |
|
1589 | pf = os.path.join(d, p) | |
|
1590 | ||
|
1591 | if pf == '-': | |
|
1592 | ui.status(_("applying patch from stdin\n")) | |
|
1593 |
|
|
|
1594 | else: | |
|
1595 | ui.status(_("applying %s\n") % p) | |
|
1596 | tmpname, message, user, date, branch, nodeid, p1, p2 = patch.extract(ui, file(pf, 'rb')) | |
|
1597 | ||
|
1598 | if tmpname is None: | |
|
1599 | raise util.Abort(_('no diffs found')) | |
|
1600 | ||
|
1601 | try: | |
|
1602 | cmdline_message = cmdutil.logmessage(opts) | |
|
1603 | if cmdline_message: | |
|
1604 | # pickup the cmdline msg | |
|
1605 | message = cmdline_message | |
|
1606 | elif message: | |
|
1607 | # pickup the patch msg | |
|
1608 | message = message.strip() | |
|
1590 | wlock = lock = None | |
|
1591 | try: | |
|
1592 | wlock = repo.wlock() | |
|
1593 | lock = repo.lock() | |
|
1594 | for p in patches: | |
|
1595 | pf = os.path.join(d, p) | |
|
1596 | ||
|
1597 | if pf == '-': | |
|
1598 | ui.status(_("applying patch from stdin\n")) | |
|
1599 | data = patch.extract(ui, sys.stdin) | |
|
1609 | 1600 | else: |
|
1610 | # launch the editor | |
|
1611 | message = None | |
|
1612 | ui.debug(_('message:\n%s\n') % message) | |
|
1613 | ||
|
1614 | wp = repo.workingctx().parents() | |
|
1615 | if opts.get('exact'): | |
|
1616 | if not nodeid or not p1: | |
|
1617 | raise util.Abort(_('not a mercurial patch')) | |
|
1618 | p1 = repo.lookup(p1) | |
|
1619 | p2 = repo.lookup(p2 or hex(nullid)) | |
|
1620 | ||
|
1621 | if p1 != wp[0].node(): | |
|
1622 | hg.clean(repo, p1, wlock=wlock) | |
|
1623 | repo.dirstate.setparents(p1, p2) | |
|
1624 | elif p2: | |
|
1625 | try: | |
|
1601 | ui.status(_("applying %s\n") % p) | |
|
1602 | data = patch.extract(ui, file(pf, 'rb')) | |
|
1603 | ||
|
1604 | tmpname, message, user, date, branch, nodeid, p1, p2 = data | |
|
1605 | ||
|
1606 | if tmpname is None: | |
|
1607 | raise util.Abort(_('no diffs found')) | |
|
1608 | ||
|
1609 | try: | |
|
1610 | cmdline_message = cmdutil.logmessage(opts) | |
|
1611 | if cmdline_message: | |
|
1612 | # pickup the cmdline msg | |
|
1613 | message = cmdline_message | |
|
1614 | elif message: | |
|
1615 | # pickup the patch msg | |
|
1616 | message = message.strip() | |
|
1617 | else: | |
|
1618 | # launch the editor | |
|
1619 | message = None | |
|
1620 | ui.debug(_('message:\n%s\n') % message) | |
|
1621 | ||
|
1622 | wp = repo.workingctx().parents() | |
|
1623 | if opts.get('exact'): | |
|
1624 | if not nodeid or not p1: | |
|
1625 | raise util.Abort(_('not a mercurial patch')) | |
|
1626 | 1626 | p1 = repo.lookup(p1) |
|
1627 | p2 = repo.lookup(p2) | |
|
1628 | if p1 == wp[0].node(): | |
|
1629 | repo.dirstate.setparents(p1, p2) | |
|
1630 | except hg.RepoError: | |
|
1631 | pass | |
|
1632 | if opts.get('exact') or opts.get('import_branch'): | |
|
1633 | repo.dirstate.setbranch(branch or 'default') | |
|
1634 | ||
|
1635 | files = {} | |
|
1636 | try: | |
|
1637 | fuzz = patch.patch(tmpname, ui, strip=strip, cwd=repo.root, | |
|
1638 | files=files) | |
|
1627 | p2 = repo.lookup(p2 or hex(nullid)) | |
|
1628 | ||
|
1629 | if p1 != wp[0].node(): | |
|
1630 | hg.clean(repo, p1, wlock=wlock) | |
|
1631 | repo.dirstate.setparents(p1, p2) | |
|
1632 | elif p2: | |
|
1633 | try: | |
|
1634 | p1 = repo.lookup(p1) | |
|
1635 | p2 = repo.lookup(p2) | |
|
1636 | if p1 == wp[0].node(): | |
|
1637 | repo.dirstate.setparents(p1, p2) | |
|
1638 | except hg.RepoError: | |
|
1639 | pass | |
|
1640 | if opts.get('exact') or opts.get('import_branch'): | |
|
1641 | repo.dirstate.setbranch(branch or 'default') | |
|
1642 | ||
|
1643 | files = {} | |
|
1644 | try: | |
|
1645 | fuzz = patch.patch(tmpname, ui, strip=strip, cwd=repo.root, | |
|
1646 | files=files) | |
|
1647 | finally: | |
|
1648 | files = patch.updatedir(ui, repo, files, wlock=wlock) | |
|
1649 | n = repo.commit(files, message, user, date, wlock=wlock, | |
|
1650 | lock=lock) | |
|
1651 | if opts.get('exact'): | |
|
1652 | if hex(n) != nodeid: | |
|
1653 | repo.rollback(wlock=wlock, lock=lock) | |
|
1654 | raise util.Abort(_('patch is damaged' + | |
|
1655 | ' or loses information')) | |
|
1639 | 1656 | finally: |
|
1640 | files = patch.updatedir(ui, repo, files, wlock=wlock) | |
|
1641 | n = repo.commit(files, message, user, date, wlock=wlock, lock=lock) | |
|
1642 | if opts.get('exact'): | |
|
1643 | if hex(n) != nodeid: | |
|
1644 | repo.rollback(wlock=wlock, lock=lock) | |
|
1645 | raise util.Abort(_('patch is damaged or loses information')) | |
|
1646 | finally: | |
|
1647 | os.unlink(tmpname) | |
|
1657 | os.unlink(tmpname) | |
|
1658 | finally: | |
|
1659 | del wlock, lock | |
|
1648 | 1660 | |
|
1649 | 1661 | def incoming(ui, repo, source="default", **opts): |
|
1650 | 1662 | """show new changesets found in source |
@@ -2248,15 +2260,18 b' def rename(ui, repo, *pats, **opts):' | |||
|
2248 | 2260 | before that, see hg revert. |
|
2249 | 2261 | """ |
|
2250 | 2262 | wlock = repo.wlock(False) |
|
2251 | errs, copied = docopy(ui, repo, pats, opts, wlock) | |
|
2252 | names = [] | |
|
2253 | for abs, rel, exact in copied: | |
|
2254 | if ui.verbose or not exact: | |
|
2255 | ui.status(_('removing %s\n') % rel) | |
|
2256 | names.append(abs) | |
|
2257 | if not opts.get('dry_run'): | |
|
2258 | repo.remove(names, True, wlock=wlock) | |
|
2259 | return errs | |
|
2263 | try: | |
|
2264 | errs, copied = docopy(ui, repo, pats, opts, wlock) | |
|
2265 | names = [] | |
|
2266 | for abs, rel, exact in copied: | |
|
2267 | if ui.verbose or not exact: | |
|
2268 | ui.status(_('removing %s\n') % rel) | |
|
2269 | names.append(abs) | |
|
2270 | if not opts.get('dry_run'): | |
|
2271 | repo.remove(names, True, wlock=wlock) | |
|
2272 | return errs | |
|
2273 | finally: | |
|
2274 | del wlock | |
|
2260 | 2275 | |
|
2261 | 2276 | def revert(ui, repo, *pats, **opts): |
|
2262 | 2277 | """revert files or dirs to their states as of some revision |
@@ -2310,8 +2325,6 b' def revert(ui, repo, *pats, **opts):' | |||
|
2310 | 2325 | else: |
|
2311 | 2326 | pmf = None |
|
2312 | 2327 | |
|
2313 | wlock = repo.wlock() | |
|
2314 | ||
|
2315 | 2328 | # need all matching names in dirstate and manifest of target rev, |
|
2316 | 2329 | # so have to walk both. do not print errors if files exist in one |
|
2317 | 2330 | # but not other. |
@@ -2319,113 +2332,116 b' def revert(ui, repo, *pats, **opts):' | |||
|
2319 | 2332 | names = {} |
|
2320 | 2333 | target_only = {} |
|
2321 | 2334 | |
|
2322 | # walk dirstate. | |
|
2323 | ||
|
2324 | for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, | |
|
2325 | badmatch=mf.has_key): | |
|
2326 | names[abs] = (rel, exact) | |
|
2327 | if src == 'b': | |
|
2328 | target_only[abs] = True | |
|
2329 | ||
|
2330 | # walk target manifest. | |
|
2331 | ||
|
2332 | def badmatch(path): | |
|
2333 | if path in names: | |
|
2334 |
|
|
|
2335 | path_ = path + '/' | |
|
2336 | for f in names: | |
|
2337 | if f.startswith(path_): | |
|
2335 | wlock = repo.wlock() | |
|
2336 | try: | |
|
2337 | # walk dirstate. | |
|
2338 | for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, | |
|
2339 | badmatch=mf.has_key): | |
|
2340 | names[abs] = (rel, exact) | |
|
2341 | if src == 'b': | |
|
2342 | target_only[abs] = True | |
|
2343 | ||
|
2344 | # walk target manifest. | |
|
2345 | ||
|
2346 | def badmatch(path): | |
|
2347 | if path in names: | |
|
2338 | 2348 | return True |
|
2339 | return False | |
|
2340 | ||
|
2341 | for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node, | |
|
2342 | badmatch=badmatch): | |
|
2343 | if abs in names or src == 'b': | |
|
2344 | continue | |
|
2345 | names[abs] = (rel, exact) | |
|
2346 | target_only[abs] = True | |
|
2347 | ||
|
2348 | changes = repo.status(match=names.has_key, wlock=wlock)[:5] | |
|
2349 | modified, added, removed, deleted, unknown = map(dict.fromkeys, changes) | |
|
2350 | ||
|
2351 | revert = ([], _('reverting %s\n')) | |
|
2352 | add = ([], _('adding %s\n')) | |
|
2353 | remove = ([], _('removing %s\n')) | |
|
2354 | forget = ([], _('forgetting %s\n')) | |
|
2355 |
|
|
|
2356 | update = {} | |
|
2357 | ||
|
2358 | disptable = ( | |
|
2359 | # dispatch table: | |
|
2360 | # file state | |
|
2361 | # action if in target manifest | |
|
2362 | # action if not in target manifest | |
|
2363 | # make backup if in target manifest | |
|
2364 | # make backup if not in target manifest | |
|
2365 | (modified, revert, remove, True, True), | |
|
2366 | (added, revert, forget, True, False), | |
|
2367 | (removed, undelete, None, False, False), | |
|
2368 | (deleted, revert, remove, False, False), | |
|
2369 | (unknown, add, None, True, False), | |
|
2370 | (target_only, add, None, False, False), | |
|
2371 | ) | |
|
2372 | ||
|
2373 | entries = names.items() | |
|
2374 | entries.sort() | |
|
2375 | ||
|
2376 | for abs, (rel, exact) in entries: | |
|
2377 |
|
|
|
2378 | target = repo.wjoin(abs) | |
|
2379 | def handle(xlist, dobackup): | |
|
2380 | xlist[0].append(abs) | |
|
2381 | update[abs] = 1 | |
|
2382 | if dobackup and not opts['no_backup'] and util.lexists(target): | |
|
2383 | bakname = "%s.orig" % rel | |
|
2384 | ui.note(_('saving current version of %s as %s\n') % | |
|
2385 | (rel, bakname)) | |
|
2386 | if not opts.get('dry_run'): | |
|
2387 | util.copyfile(target, bakname) | |
|
2388 | if ui.verbose or not exact: | |
|
2389 | ui.status(xlist[1] % rel) | |
|
2390 | for table, hitlist, misslist, backuphit, backupmiss in disptable: | |
|
2391 | if abs not in table: continue | |
|
2392 | # file has changed in dirstate | |
|
2393 | if mfentry: | |
|
2394 | handle(hitlist, backuphit) | |
|
2395 | elif misslist is not None: | |
|
2396 | handle(misslist, backupmiss) | |
|
2349 | path_ = path + '/' | |
|
2350 | for f in names: | |
|
2351 | if f.startswith(path_): | |
|
2352 | return True | |
|
2353 | return False | |
|
2354 | ||
|
2355 | for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node, | |
|
2356 | badmatch=badmatch): | |
|
2357 | if abs in names or src == 'b': | |
|
2358 | continue | |
|
2359 | names[abs] = (rel, exact) | |
|
2360 | target_only[abs] = True | |
|
2361 | ||
|
2362 | changes = repo.status(match=names.has_key, wlock=wlock)[:5] | |
|
2363 | modified, added, removed, deleted, unknown = map(dict.fromkeys, changes) | |
|
2364 | ||
|
2365 | revert = ([], _('reverting %s\n')) | |
|
2366 | add = ([], _('adding %s\n')) | |
|
2367 | remove = ([], _('removing %s\n')) | |
|
2368 | forget = ([], _('forgetting %s\n')) | |
|
2369 | undelete = ([], _('undeleting %s\n')) | |
|
2370 | update = {} | |
|
2371 | ||
|
2372 | disptable = ( | |
|
2373 | # dispatch table: | |
|
2374 | # file state | |
|
2375 | # action if in target manifest | |
|
2376 | # action if not in target manifest | |
|
2377 | # make backup if in target manifest | |
|
2378 | # make backup if not in target manifest | |
|
2379 | (modified, revert, remove, True, True), | |
|
2380 | (added, revert, forget, True, False), | |
|
2381 | (removed, undelete, None, False, False), | |
|
2382 | (deleted, revert, remove, False, False), | |
|
2383 | (unknown, add, None, True, False), | |
|
2384 | (target_only, add, None, False, False), | |
|
2385 | ) | |
|
2386 | ||
|
2387 | entries = names.items() | |
|
2388 | entries.sort() | |
|
2389 | ||
|
2390 | for abs, (rel, exact) in entries: | |
|
2391 | mfentry = mf.get(abs) | |
|
2392 | target = repo.wjoin(abs) | |
|
2393 | def handle(xlist, dobackup): | |
|
2394 | xlist[0].append(abs) | |
|
2395 | update[abs] = 1 | |
|
2396 | if dobackup and not opts['no_backup'] and util.lexists(target): | |
|
2397 | bakname = "%s.orig" % rel | |
|
2398 | ui.note(_('saving current version of %s as %s\n') % | |
|
2399 | (rel, bakname)) | |
|
2400 | if not opts.get('dry_run'): | |
|
2401 | util.copyfile(target, bakname) | |
|
2402 | if ui.verbose or not exact: | |
|
2403 | ui.status(xlist[1] % rel) | |
|
2404 | for table, hitlist, misslist, backuphit, backupmiss in disptable: | |
|
2405 | if abs not in table: continue | |
|
2406 | # file has changed in dirstate | |
|
2407 | if mfentry: | |
|
2408 | handle(hitlist, backuphit) | |
|
2409 | elif misslist is not None: | |
|
2410 | handle(misslist, backupmiss) | |
|
2411 | else: | |
|
2412 | if exact: ui.warn(_('file not managed: %s\n') % rel) | |
|
2413 | break | |
|
2397 | 2414 | else: |
|
2398 | if exact: ui.warn(_('file not managed: %s\n') % rel) | |
|
2399 | break | |
|
2400 | else: | |
|
2401 | # file has not changed in dirstate | |
|
2402 | if node == parent: | |
|
2403 | if exact: ui.warn(_('no changes needed to %s\n') % rel) | |
|
2404 | continue | |
|
2405 | if pmf is None: | |
|
2406 | # only need parent manifest in this unlikely case, | |
|
2407 |
|
|
|
2408 | pmf = repo.changectx(parent).manifest() | |
|
2409 | if abs in pmf: | |
|
2410 | if mfentry: | |
|
2411 | # if version of file is same in parent and target | |
|
2412 |
|
|
|
2413 | if pmf[abs] != mfentry: | |
|
2414 | handle(revert, False) | |
|
2415 | else: | |
|
2416 | handle(remove, False) | |
|
2417 | ||
|
2418 | if not opts.get('dry_run'): | |
|
2419 |
for f in |
|
|
2420 |
repo.dirstate. |
|
|
2421 | r = hg.revert(repo, node, update.has_key, wlock) | |
|
2422 | for f in add[0]: | |
|
2423 | repo.dirstate.add(f) | |
|
2424 | for f in undelete[0]: | |
|
2425 |
re |
|
|
2426 | for f in remove[0]: | |
|
2427 | repo.dirstate.remove(f) | |
|
2428 | return r | |
|
2415 | # file has not changed in dirstate | |
|
2416 | if node == parent: | |
|
2417 | if exact: ui.warn(_('no changes needed to %s\n') % rel) | |
|
2418 | continue | |
|
2419 | if pmf is None: | |
|
2420 | # only need parent manifest in this unlikely case, | |
|
2421 | # so do not read by default | |
|
2422 | pmf = repo.changectx(parent).manifest() | |
|
2423 | if abs in pmf: | |
|
2424 | if mfentry: | |
|
2425 | # if version of file is same in parent and target | |
|
2426 | # manifests, do nothing | |
|
2427 | if pmf[abs] != mfentry: | |
|
2428 | handle(revert, False) | |
|
2429 | else: | |
|
2430 | handle(remove, False) | |
|
2431 | ||
|
2432 | if not opts.get('dry_run'): | |
|
2433 | for f in forget[0]: | |
|
2434 | repo.dirstate.forget(f) | |
|
2435 | r = hg.revert(repo, node, update.has_key, wlock) | |
|
2436 | for f in add[0]: | |
|
2437 | repo.dirstate.add(f) | |
|
2438 | for f in undelete[0]: | |
|
2439 | repo.dirstate.normal(f) | |
|
2440 | for f in remove[0]: | |
|
2441 | repo.dirstate.remove(f) | |
|
2442 | return r | |
|
2443 | finally: | |
|
2444 | del wlock | |
|
2429 | 2445 | |
|
2430 | 2446 | def rollback(ui, repo): |
|
2431 | 2447 | """roll back the last transaction in this repository |
@@ -130,103 +130,99 b' def clone(ui, source, dest=None, pull=Fa' | |||
|
130 | 130 | if self.dir_: |
|
131 | 131 | self.rmtree(self.dir_, True) |
|
132 | 132 | |
|
133 | dir_cleanup = None | |
|
134 | if islocal(dest): | |
|
135 | dir_cleanup = DirCleanup(dest) | |
|
133 | src_lock = dest_lock = dir_cleanup = None | |
|
134 | try: | |
|
135 | if islocal(dest): | |
|
136 | dir_cleanup = DirCleanup(dest) | |
|
136 | 137 | |
|
137 | abspath = origsource | |
|
138 | copy = False | |
|
139 | if src_repo.local() and islocal(dest): | |
|
140 | abspath = os.path.abspath(origsource) | |
|
141 | copy = not pull and not rev | |
|
138 | abspath = origsource | |
|
139 | copy = False | |
|
140 | if src_repo.local() and islocal(dest): | |
|
141 | abspath = os.path.abspath(origsource) | |
|
142 | copy = not pull and not rev | |
|
142 | 143 | |
|
143 | src_lock, dest_lock = None, None | |
|
144 | if copy: | |
|
145 | try: | |
|
146 | # we use a lock here because if we race with commit, we | |
|
147 | # can end up with extra data in the cloned revlogs that's | |
|
148 | # not pointed to by changesets, thus causing verify to | |
|
149 | # fail | |
|
150 | src_lock = src_repo.lock() | |
|
151 | except lock.LockException: | |
|
152 | copy = False | |
|
144 | if copy: | |
|
145 | try: | |
|
146 | # we use a lock here because if we race with commit, we | |
|
147 | # can end up with extra data in the cloned revlogs that's | |
|
148 | # not pointed to by changesets, thus causing verify to | |
|
149 | # fail | |
|
150 | src_lock = src_repo.lock() | |
|
151 | except lock.LockException: | |
|
152 | copy = False | |
|
153 | 153 | |
|
154 | if copy: | |
|
155 | def force_copy(src, dst): | |
|
156 | try: | |
|
157 | util.copyfiles(src, dst) | |
|
158 | except OSError, inst: | |
|
159 | if inst.errno != errno.ENOENT: | |
|
160 | raise | |
|
154 | if copy: | |
|
155 | def force_copy(src, dst): | |
|
156 | try: | |
|
157 | util.copyfiles(src, dst) | |
|
158 | except OSError, inst: | |
|
159 | if inst.errno != errno.ENOENT: | |
|
160 | raise | |
|
161 | 161 | |
|
162 | src_store = os.path.realpath(src_repo.spath) | |
|
163 | if not os.path.exists(dest): | |
|
164 | os.mkdir(dest) | |
|
165 | dest_path = os.path.realpath(os.path.join(dest, ".hg")) | |
|
166 | os.mkdir(dest_path) | |
|
167 | if src_repo.spath != src_repo.path: | |
|
168 | dest_store = os.path.join(dest_path, "store") | |
|
169 | os.mkdir(dest_store) | |
|
170 | else: | |
|
171 | dest_store = dest_path | |
|
172 | # copy the requires file | |
|
173 | force_copy(src_repo.join("requires"), | |
|
174 | os.path.join(dest_path, "requires")) | |
|
175 | # we lock here to avoid premature writing to the target | |
|
176 | dest_lock = lock.lock(os.path.join(dest_store, "lock")) | |
|
162 | src_store = os.path.realpath(src_repo.spath) | |
|
163 | if not os.path.exists(dest): | |
|
164 | os.mkdir(dest) | |
|
165 | dest_path = os.path.realpath(os.path.join(dest, ".hg")) | |
|
166 | os.mkdir(dest_path) | |
|
167 | if src_repo.spath != src_repo.path: | |
|
168 | dest_store = os.path.join(dest_path, "store") | |
|
169 | os.mkdir(dest_store) | |
|
170 | else: | |
|
171 | dest_store = dest_path | |
|
172 | # copy the requires file | |
|
173 | force_copy(src_repo.join("requires"), | |
|
174 | os.path.join(dest_path, "requires")) | |
|
175 | # we lock here to avoid premature writing to the target | |
|
176 | dest_lock = lock.lock(os.path.join(dest_store, "lock")) | |
|
177 | 177 | |
|
178 | files = ("data", | |
|
179 | "00manifest.d", "00manifest.i", | |
|
180 | "00changelog.d", "00changelog.i") | |
|
181 | for f in files: | |
|
182 | src = os.path.join(src_store, f) | |
|
183 | dst = os.path.join(dest_store, f) | |
|
184 | force_copy(src, dst) | |
|
178 | files = ("data", | |
|
179 | "00manifest.d", "00manifest.i", | |
|
180 | "00changelog.d", "00changelog.i") | |
|
181 | for f in files: | |
|
182 | src = os.path.join(src_store, f) | |
|
183 | dst = os.path.join(dest_store, f) | |
|
184 | force_copy(src, dst) | |
|
185 | ||
|
186 | # we need to re-init the repo after manually copying the data | |
|
187 | # into it | |
|
188 | dest_repo = repository(ui, dest) | |
|
189 | ||
|
190 | else: | |
|
191 | dest_repo = repository(ui, dest, create=True) | |
|
185 | 192 | |
|
186 | # we need to re-init the repo after manually copying the data | |
|
187 |
|
|
|
188 | dest_repo = repository(ui, dest) | |
|
189 | ||
|
190 | else: | |
|
191 | dest_repo = repository(ui, dest, create=True) | |
|
193 | revs = None | |
|
194 | if rev: | |
|
195 | if 'lookup' not in src_repo.capabilities: | |
|
196 | raise util.Abort(_("src repository does not support revision " | |
|
197 | "lookup and so doesn't support clone by " | |
|
198 | "revision")) | |
|
199 | revs = [src_repo.lookup(r) for r in rev] | |
|
192 | 200 | |
|
193 | revs = None | |
|
194 | if rev: | |
|
195 |
|
|
|
196 | raise util.Abort(_("src repository does not support revision " | |
|
197 | "lookup and so doesn't support clone by " | |
|
198 | "revision")) | |
|
199 | revs = [src_repo.lookup(r) for r in rev] | |
|
201 | if dest_repo.local(): | |
|
202 | dest_repo.clone(src_repo, heads=revs, stream=stream) | |
|
203 | elif src_repo.local(): | |
|
204 | src_repo.push(dest_repo, revs=revs) | |
|
205 | else: | |
|
206 | raise util.Abort(_("clone from remote to remote not supported")) | |
|
200 | 207 | |
|
201 | 208 | if dest_repo.local(): |
|
202 | dest_repo.clone(src_repo, heads=revs, stream=stream) | |
|
203 | elif src_repo.local(): | |
|
204 | src_repo.push(dest_repo, revs=revs) | |
|
205 |
|
|
|
206 | raise util.Abort(_("clone from remote to remote not supported")) | |
|
207 | ||
|
208 | if src_lock: | |
|
209 | src_lock.release() | |
|
209 | fp = dest_repo.opener("hgrc", "w", text=True) | |
|
210 | fp.write("[paths]\n") | |
|
211 | fp.write("default = %s\n" % abspath) | |
|
212 | fp.close() | |
|
210 | 213 | |
|
211 | if dest_repo.local(): | |
|
212 | fp = dest_repo.opener("hgrc", "w", text=True) | |
|
213 | fp.write("[paths]\n") | |
|
214 | fp.write("default = %s\n" % abspath) | |
|
215 | fp.close() | |
|
216 | ||
|
217 |
if d |
|
|
218 |
d |
|
|
214 | if update: | |
|
215 | try: | |
|
216 | checkout = dest_repo.lookup("default") | |
|
217 | except: | |
|
218 | checkout = dest_repo.changelog.tip() | |
|
219 | _update(dest_repo, checkout) | |
|
220 | if dir_cleanup: | |
|
221 | dir_cleanup.close() | |
|
219 | 222 | |
|
220 | if update: | |
|
221 | try: | |
|
222 | checkout = dest_repo.lookup("default") | |
|
223 | except: | |
|
224 | checkout = dest_repo.changelog.tip() | |
|
225 | _update(dest_repo, checkout) | |
|
226 | if dir_cleanup: | |
|
227 | dir_cleanup.close() | |
|
228 | ||
|
229 | return src_repo, dest_repo | |
|
223 | return src_repo, dest_repo | |
|
224 | finally: | |
|
225 | del src_lock, dest_lock, dir_cleanup | |
|
230 | 226 | |
|
231 | 227 | def _showstats(repo, stats): |
|
232 | 228 | stats = ((stats[0], _("updated")), |
@@ -1168,7 +1168,7 b' class hgweb(object):' | |||
|
1168 | 1168 | req.write('%d\n' % ret) |
|
1169 | 1169 | req.write(val) |
|
1170 | 1170 | finally: |
|
1171 |
lock |
|
|
1171 | del lock | |
|
1172 | 1172 | except (OSError, IOError), inst: |
|
1173 | 1173 | req.write('0\n') |
|
1174 | 1174 | filename = getattr(inst, 'filename', '') |
This diff has been collapsed as it changes many lines, (628 lines changed) Show them Hide them | |||
@@ -516,28 +516,34 b' class localrepository(repo.repository):' | |||
|
516 | 516 | |
|
517 | 517 | def recover(self): |
|
518 | 518 | l = self.lock() |
|
519 | if os.path.exists(self.sjoin("journal")): | |
|
520 | self.ui.status(_("rolling back interrupted transaction\n")) | |
|
521 | transaction.rollback(self.sopener, self.sjoin("journal")) | |
|
522 | self.invalidate() | |
|
523 | return True | |
|
524 | else: | |
|
525 | self.ui.warn(_("no interrupted transaction available\n")) | |
|
526 | return False | |
|
519 | try: | |
|
520 | if os.path.exists(self.sjoin("journal")): | |
|
521 | self.ui.status(_("rolling back interrupted transaction\n")) | |
|
522 | transaction.rollback(self.sopener, self.sjoin("journal")) | |
|
523 | self.invalidate() | |
|
524 | return True | |
|
525 | else: | |
|
526 | self.ui.warn(_("no interrupted transaction available\n")) | |
|
527 | return False | |
|
528 | finally: | |
|
529 | del l | |
|
527 | 530 | |
|
528 | 531 | def rollback(self, wlock=None, lock=None): |
|
529 |
|
|
|
530 | wlock = self.wlock() | |
|
531 | if not lock: | |
|
532 | lock = self.lock() | |
|
533 | if os.path.exists(self.sjoin("undo")): | |
|
534 | self.ui.status(_("rolling back last transaction\n")) | |
|
535 | transaction.rollback(self.sopener, self.sjoin("undo")) | |
|
536 | util.rename(self.join("undo.dirstate"), self.join("dirstate")) | |
|
537 | self.invalidate() | |
|
538 |
self |
|
|
539 | else: | |
|
540 | self.ui.warn(_("no rollback information available\n")) | |
|
532 | try: | |
|
533 | if not wlock: | |
|
534 | wlock = self.wlock() | |
|
535 | if not lock: | |
|
536 | lock = self.lock() | |
|
537 | if os.path.exists(self.sjoin("undo")): | |
|
538 | self.ui.status(_("rolling back last transaction\n")) | |
|
539 | transaction.rollback(self.sopener, self.sjoin("undo")) | |
|
540 | util.rename(self.join("undo.dirstate"), self.join("dirstate")) | |
|
541 | self.invalidate() | |
|
542 | self.dirstate.invalidate() | |
|
543 | else: | |
|
544 | self.ui.warn(_("no rollback information available\n")) | |
|
545 | finally: | |
|
546 | del wlock, lock | |
|
541 | 547 | |
|
542 | 548 | def invalidate(self): |
|
543 | 549 | for a in "changelog manifest".split(): |
@@ -639,164 +645,169 b' class localrepository(repo.repository):' | |||
|
639 | 645 | def commit(self, files=None, text="", user=None, date=None, |
|
640 | 646 | match=util.always, force=False, lock=None, wlock=None, |
|
641 | 647 | force_editor=False, p1=None, p2=None, extra={}): |
|
642 | ||
|
643 | commit = [] | |
|
644 |
|
|
|
645 |
|
|
|
646 | use_dirstate = (p1 is None) # not rawcommit | |
|
647 | extra = extra.copy() | |
|
648 | tr = None | |
|
649 | try: | |
|
650 | commit = [] | |
|
651 | remove = [] | |
|
652 | changed = [] | |
|
653 | use_dirstate = (p1 is None) # not rawcommit | |
|
654 | extra = extra.copy() | |
|
648 | 655 | |
|
649 | if use_dirstate: | |
|
650 | if files: | |
|
651 | for f in files: | |
|
652 | s = self.dirstate[f] | |
|
653 | if s in 'nma': | |
|
654 | commit.append(f) | |
|
655 | elif s == 'r': | |
|
656 | remove.append(f) | |
|
657 | else: | |
|
658 | self.ui.warn(_("%s not tracked!\n") % f) | |
|
656 | if use_dirstate: | |
|
657 | if files: | |
|
658 | for f in files: | |
|
659 | s = self.dirstate[f] | |
|
660 | if s in 'nma': | |
|
661 | commit.append(f) | |
|
662 | elif s == 'r': | |
|
663 | remove.append(f) | |
|
664 | else: | |
|
665 | self.ui.warn(_("%s not tracked!\n") % f) | |
|
666 | else: | |
|
667 | changes = self.status(match=match)[:5] | |
|
668 | modified, added, removed, deleted, unknown = changes | |
|
669 | commit = modified + added | |
|
670 | remove = removed | |
|
659 | 671 | else: |
|
660 | changes = self.status(match=match)[:5] | |
|
661 | modified, added, removed, deleted, unknown = changes | |
|
662 | commit = modified + added | |
|
663 | remove = removed | |
|
664 | else: | |
|
665 | commit = files | |
|
672 | commit = files | |
|
666 | 673 | |
|
667 | if use_dirstate: | |
|
668 | p1, p2 = self.dirstate.parents() | |
|
669 | update_dirstate = True | |
|
670 | else: | |
|
671 | p1, p2 = p1, p2 or nullid | |
|
672 | update_dirstate = (self.dirstate.parents()[0] == p1) | |
|
674 | if use_dirstate: | |
|
675 | p1, p2 = self.dirstate.parents() | |
|
676 | update_dirstate = True | |
|
677 | else: | |
|
678 | p1, p2 = p1, p2 or nullid | |
|
679 | update_dirstate = (self.dirstate.parents()[0] == p1) | |
|
673 | 680 | |
|
674 | c1 = self.changelog.read(p1) | |
|
675 | c2 = self.changelog.read(p2) | |
|
676 | m1 = self.manifest.read(c1[0]).copy() | |
|
677 | m2 = self.manifest.read(c2[0]) | |
|
681 | c1 = self.changelog.read(p1) | |
|
682 | c2 = self.changelog.read(p2) | |
|
683 | m1 = self.manifest.read(c1[0]).copy() | |
|
684 | m2 = self.manifest.read(c2[0]) | |
|
678 | 685 | |
|
679 | if use_dirstate: | |
|
680 | branchname = self.workingctx().branch() | |
|
681 | try: | |
|
682 | branchname = branchname.decode('UTF-8').encode('UTF-8') | |
|
683 | except UnicodeDecodeError: | |
|
684 | raise util.Abort(_('branch name not in UTF-8!')) | |
|
685 | else: | |
|
686 | branchname = "" | |
|
686 | if use_dirstate: | |
|
687 | branchname = self.workingctx().branch() | |
|
688 | try: | |
|
689 | branchname = branchname.decode('UTF-8').encode('UTF-8') | |
|
690 | except UnicodeDecodeError: | |
|
691 | raise util.Abort(_('branch name not in UTF-8!')) | |
|
692 | else: | |
|
693 | branchname = "" | |
|
687 | 694 | |
|
688 | if use_dirstate: | |
|
689 | oldname = c1[5].get("branch") # stored in UTF-8 | |
|
690 | if (not commit and not remove and not force and p2 == nullid | |
|
691 | and branchname == oldname): | |
|
692 | self.ui.status(_("nothing changed\n")) | |
|
693 | return None | |
|
695 | if use_dirstate: | |
|
696 | oldname = c1[5].get("branch") # stored in UTF-8 | |
|
697 | if (not commit and not remove and not force and p2 == nullid | |
|
698 | and branchname == oldname): | |
|
699 | self.ui.status(_("nothing changed\n")) | |
|
700 | return None | |
|
694 | 701 | |
|
695 | xp1 = hex(p1) | |
|
696 | if p2 == nullid: xp2 = '' | |
|
697 | else: xp2 = hex(p2) | |
|
702 | xp1 = hex(p1) | |
|
703 | if p2 == nullid: xp2 = '' | |
|
704 | else: xp2 = hex(p2) | |
|
698 | 705 | |
|
699 | self.hook("precommit", throw=True, parent1=xp1, parent2=xp2) | |
|
706 | self.hook("precommit", throw=True, parent1=xp1, parent2=xp2) | |
|
700 | 707 | |
|
701 | if not wlock: | |
|
702 | wlock = self.wlock() | |
|
703 | if not lock: | |
|
704 | lock = self.lock() | |
|
705 | tr = self.transaction() | |
|
708 | if not wlock: | |
|
709 | wlock = self.wlock() | |
|
710 | if not lock: | |
|
711 | lock = self.lock() | |
|
712 | tr = self.transaction() | |
|
706 | 713 | |
|
707 | # check in files | |
|
708 | new = {} | |
|
709 | linkrev = self.changelog.count() | |
|
710 | commit.sort() | |
|
711 | is_exec = util.execfunc(self.root, m1.execf) | |
|
712 | is_link = util.linkfunc(self.root, m1.linkf) | |
|
713 | for f in commit: | |
|
714 | self.ui.note(f + "\n") | |
|
715 | try: | |
|
716 | new[f] = self.filecommit(f, m1, m2, linkrev, tr, changed) | |
|
717 | new_exec = is_exec(f) | |
|
718 | new_link = is_link(f) | |
|
719 | if not changed or changed[-1] != f: | |
|
720 |
# mention the file in the changelog if some |
|
|
721 |
# even if there was no content |
|
|
722 | old_exec = m1.execf(f) | |
|
723 |
|
|
|
724 |
|
|
|
725 | changed.append(f) | |
|
726 | m1.set(f, new_exec, new_link) | |
|
727 | except (OSError, IOError): | |
|
728 | if use_dirstate: | |
|
729 | self.ui.warn(_("trouble committing %s!\n") % f) | |
|
730 | raise | |
|
731 |
|
|
|
732 |
|
|
|
714 | # check in files | |
|
715 | new = {} | |
|
716 | linkrev = self.changelog.count() | |
|
717 | commit.sort() | |
|
718 | is_exec = util.execfunc(self.root, m1.execf) | |
|
719 | is_link = util.linkfunc(self.root, m1.linkf) | |
|
720 | for f in commit: | |
|
721 | self.ui.note(f + "\n") | |
|
722 | try: | |
|
723 | new[f] = self.filecommit(f, m1, m2, linkrev, tr, changed) | |
|
724 | new_exec = is_exec(f) | |
|
725 | new_link = is_link(f) | |
|
726 | if not changed or changed[-1] != f: | |
|
727 | # mention the file in the changelog if some | |
|
728 | # flag changed, even if there was no content | |
|
729 | # change. | |
|
730 | old_exec = m1.execf(f) | |
|
731 | old_link = m1.linkf(f) | |
|
732 | if old_exec != new_exec or old_link != new_link: | |
|
733 | changed.append(f) | |
|
734 | m1.set(f, new_exec, new_link) | |
|
735 | except (OSError, IOError): | |
|
736 | if use_dirstate: | |
|
737 | self.ui.warn(_("trouble committing %s!\n") % f) | |
|
738 | raise | |
|
739 | else: | |
|
740 | remove.append(f) | |
|
733 | 741 | |
|
734 | # update manifest | |
|
735 | m1.update(new) | |
|
736 | remove.sort() | |
|
737 | removed = [] | |
|
742 | # update manifest | |
|
743 | m1.update(new) | |
|
744 | remove.sort() | |
|
745 | removed = [] | |
|
738 | 746 | |
|
739 | for f in remove: | |
|
740 | if f in m1: | |
|
741 | del m1[f] | |
|
742 | removed.append(f) | |
|
743 | elif f in m2: | |
|
744 | removed.append(f) | |
|
745 |
mn = self.manifest.add(m1, tr, linkrev, c1[0], c2[0], |
|
|
747 | for f in remove: | |
|
748 | if f in m1: | |
|
749 | del m1[f] | |
|
750 | removed.append(f) | |
|
751 | elif f in m2: | |
|
752 | removed.append(f) | |
|
753 | mn = self.manifest.add(m1, tr, linkrev, c1[0], c2[0], | |
|
754 | (new, removed)) | |
|
746 | 755 | |
|
747 | # add changeset | |
|
748 | new = new.keys() | |
|
749 | new.sort() | |
|
756 | # add changeset | |
|
757 | new = new.keys() | |
|
758 | new.sort() | |
|
750 | 759 | |
|
751 | user = user or self.ui.username() | |
|
752 | if not text or force_editor: | |
|
753 | edittext = [] | |
|
754 | if text: | |
|
755 | edittext.append(text) | |
|
756 | edittext.append("") | |
|
757 | edittext.append("HG: user: %s" % user) | |
|
758 | if p2 != nullid: | |
|
759 | edittext.append("HG: branch merge") | |
|
760 | if branchname: | |
|
761 | edittext.append("HG: branch %s" % util.tolocal(branchname)) | |
|
762 | edittext.extend(["HG: changed %s" % f for f in changed]) | |
|
763 | edittext.extend(["HG: removed %s" % f for f in removed]) | |
|
764 | if not changed and not remove: | |
|
765 | edittext.append("HG: no files changed") | |
|
766 | edittext.append("") | |
|
767 | # run editor in the repository root | |
|
768 | olddir = os.getcwd() | |
|
769 | os.chdir(self.root) | |
|
770 | text = self.ui.edit("\n".join(edittext), user) | |
|
771 | os.chdir(olddir) | |
|
760 | user = user or self.ui.username() | |
|
761 | if not text or force_editor: | |
|
762 | edittext = [] | |
|
763 | if text: | |
|
764 | edittext.append(text) | |
|
765 | edittext.append("") | |
|
766 | edittext.append("HG: user: %s" % user) | |
|
767 | if p2 != nullid: | |
|
768 | edittext.append("HG: branch merge") | |
|
769 | if branchname: | |
|
770 | edittext.append("HG: branch %s" % util.tolocal(branchname)) | |
|
771 | edittext.extend(["HG: changed %s" % f for f in changed]) | |
|
772 | edittext.extend(["HG: removed %s" % f for f in removed]) | |
|
773 | if not changed and not remove: | |
|
774 | edittext.append("HG: no files changed") | |
|
775 | edittext.append("") | |
|
776 | # run editor in the repository root | |
|
777 | olddir = os.getcwd() | |
|
778 | os.chdir(self.root) | |
|
779 | text = self.ui.edit("\n".join(edittext), user) | |
|
780 | os.chdir(olddir) | |
|
772 | 781 | |
|
773 | lines = [line.rstrip() for line in text.rstrip().splitlines()] | |
|
774 | while lines and not lines[0]: | |
|
775 | del lines[0] | |
|
776 | if not lines: | |
|
777 | return None | |
|
778 | text = '\n'.join(lines) | |
|
779 | if branchname: | |
|
780 | extra["branch"] = branchname | |
|
781 | n = self.changelog.add(mn, changed + removed, text, tr, p1, p2, | |
|
782 | user, date, extra) | |
|
783 | self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1, | |
|
784 | parent2=xp2) | |
|
785 | tr.close() | |
|
782 | lines = [line.rstrip() for line in text.rstrip().splitlines()] | |
|
783 | while lines and not lines[0]: | |
|
784 | del lines[0] | |
|
785 | if not lines: | |
|
786 | return None | |
|
787 | text = '\n'.join(lines) | |
|
788 | if branchname: | |
|
789 | extra["branch"] = branchname | |
|
790 | n = self.changelog.add(mn, changed + removed, text, tr, p1, p2, | |
|
791 | user, date, extra) | |
|
792 | self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1, | |
|
793 | parent2=xp2) | |
|
794 | tr.close() | |
|
786 | 795 | |
|
787 | if self.branchcache and "branch" in extra: | |
|
788 | self.branchcache[util.tolocal(extra["branch"])] = n | |
|
796 | if self.branchcache and "branch" in extra: | |
|
797 | self.branchcache[util.tolocal(extra["branch"])] = n | |
|
789 | 798 | |
|
790 | if use_dirstate or update_dirstate: | |
|
791 | self.dirstate.setparents(n) | |
|
792 | if use_dirstate: | |
|
793 | for f in new: | |
|
794 | self.dirstate.normal(f) | |
|
795 | for f in removed: | |
|
796 | self.dirstate.forget(f) | |
|
799 | if use_dirstate or update_dirstate: | |
|
800 | self.dirstate.setparents(n) | |
|
801 | if use_dirstate: | |
|
802 | for f in new: | |
|
803 | self.dirstate.normal(f) | |
|
804 | for f in removed: | |
|
805 | self.dirstate.forget(f) | |
|
797 | 806 | |
|
798 | self.hook("commit", node=hex(n), parent1=xp1, parent2=xp2) | |
|
799 | return n | |
|
807 | self.hook("commit", node=hex(n), parent1=xp1, parent2=xp2) | |
|
808 | return n | |
|
809 | finally: | |
|
810 | del lock, wlock, tr | |
|
800 | 811 | |
|
801 | 812 | def walk(self, node=None, files=[], match=util.always, badmatch=None): |
|
802 | 813 | ''' |
@@ -895,18 +906,18 b' class localrepository(repo.repository):' | |||
|
895 | 906 | |
|
896 | 907 | # update dirstate for files that are actually clean |
|
897 | 908 | if fixup: |
|
898 |
|
|
|
899 |
|
|
|
900 |
|
|
|
901 |
|
|
|
902 |
|
|
|
903 | except lock.LockException: | |
|
904 | pass | |
|
905 |
if |
|
|
906 | for f in fixup: | |
|
907 | self.dirstate.normal(f) | |
|
908 |
|
|
|
909 |
|
|
|
909 | fixlock = wlock | |
|
910 | try: | |
|
911 | if not fixlock: | |
|
912 | try: | |
|
913 | fixlock = self.wlock(False) | |
|
914 | except lock.LockException: | |
|
915 | pass | |
|
916 | if fixlock: | |
|
917 | for f in fixup: | |
|
918 | self.dirstate.normal(f) | |
|
919 | finally: | |
|
920 | del fixlock | |
|
910 | 921 | else: |
|
911 | 922 | # we are comparing working dir against non-parent |
|
912 | 923 | # generate a pseudo-manifest for the working dir |
@@ -954,84 +965,99 b' class localrepository(repo.repository):' | |||
|
954 | 965 | return (modified, added, removed, deleted, unknown, ignored, clean) |
|
955 | 966 | |
|
956 | 967 | def add(self, list, wlock=None): |
|
957 |
|
|
|
958 | wlock = self.wlock() | |
|
959 | for f in list: | |
|
960 | p = self.wjoin(f) | |
|
961 | try: | |
|
962 |
|
|
|
963 | except: | |
|
964 | self.ui.warn(_("%s does not exist!\n") % f) | |
|
965 | continue | |
|
966 | if st.st_size > 10000000: | |
|
967 | self.ui.warn(_("%s: files over 10MB may cause memory and" | |
|
968 | " performance problems\n" | |
|
969 |
" |
|
|
970 |
|
|
|
971 | if not (stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode)): | |
|
972 | self.ui.warn(_("%s not added: only files and symlinks " | |
|
973 | "supported currently\n") % f) | |
|
974 | elif self.dirstate[f] in 'an': | |
|
975 | self.ui.warn(_("%s already tracked!\n") % f) | |
|
976 | else: | |
|
977 |
|
|
|
968 | try: | |
|
969 | if not wlock: | |
|
970 | wlock = self.wlock() | |
|
971 | for f in list: | |
|
972 | p = self.wjoin(f) | |
|
973 | try: | |
|
974 | st = os.lstat(p) | |
|
975 | except: | |
|
976 | self.ui.warn(_("%s does not exist!\n") % f) | |
|
977 | continue | |
|
978 | if st.st_size > 10000000: | |
|
979 | self.ui.warn(_("%s: files over 10MB may cause memory and" | |
|
980 | " performance problems\n" | |
|
981 | "(use 'hg revert %s' to unadd the file)\n") | |
|
982 | % (f, f)) | |
|
983 | if not (stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode)): | |
|
984 | self.ui.warn(_("%s not added: only files and symlinks " | |
|
985 | "supported currently\n") % f) | |
|
986 | elif self.dirstate[f] in 'an': | |
|
987 | self.ui.warn(_("%s already tracked!\n") % f) | |
|
988 | else: | |
|
989 | self.dirstate.add(f) | |
|
990 | finally: | |
|
991 | del wlock | |
|
978 | 992 | |
|
979 | 993 | def forget(self, list, wlock=None): |
|
980 |
|
|
|
981 | wlock = self.wlock() | |
|
982 | for f in list: | |
|
983 | if self.dirstate[f] != 'a': | |
|
984 | self.ui.warn(_("%s not added!\n") % f) | |
|
985 | else: | |
|
986 |
|
|
|
994 | try: | |
|
995 | if not wlock: | |
|
996 | wlock = self.wlock() | |
|
997 | for f in list: | |
|
998 | if self.dirstate[f] != 'a': | |
|
999 | self.ui.warn(_("%s not added!\n") % f) | |
|
1000 | else: | |
|
1001 | self.dirstate.forget(f) | |
|
1002 | finally: | |
|
1003 | del wlock | |
|
987 | 1004 | |
|
988 | 1005 | def remove(self, list, unlink=False, wlock=None): |
|
989 |
|
|
|
1006 | try: | |
|
1007 | if unlink: | |
|
1008 | for f in list: | |
|
1009 | try: | |
|
1010 | util.unlink(self.wjoin(f)) | |
|
1011 | except OSError, inst: | |
|
1012 | if inst.errno != errno.ENOENT: | |
|
1013 | raise | |
|
1014 | if not wlock: | |
|
1015 | wlock = self.wlock() | |
|
990 | 1016 | for f in list: |
|
991 | try: | |
|
992 | util.unlink(self.wjoin(f)) | |
|
993 | except OSError, inst: | |
|
994 | if inst.errno != errno.ENOENT: | |
|
995 |
|
|
|
996 | if not wlock: | |
|
997 | wlock = self.wlock() | |
|
998 | for f in list: | |
|
999 | if unlink and os.path.exists(self.wjoin(f)): | |
|
1000 | self.ui.warn(_("%s still exists!\n") % f) | |
|
1001 | elif self.dirstate[f] == 'a': | |
|
1002 | self.dirstate.forget(f) | |
|
1003 | elif f not in self.dirstate: | |
|
1004 | self.ui.warn(_("%s not tracked!\n") % f) | |
|
1005 | else: | |
|
1006 | self.dirstate.remove(f) | |
|
1017 | if unlink and os.path.exists(self.wjoin(f)): | |
|
1018 | self.ui.warn(_("%s still exists!\n") % f) | |
|
1019 | elif self.dirstate[f] == 'a': | |
|
1020 | self.dirstate.forget(f) | |
|
1021 | elif f not in self.dirstate: | |
|
1022 | self.ui.warn(_("%s not tracked!\n") % f) | |
|
1023 | else: | |
|
1024 | self.dirstate.remove(f) | |
|
1025 | finally: | |
|
1026 | del wlock | |
|
1007 | 1027 | |
|
1008 | 1028 | def undelete(self, list, wlock=None): |
|
1009 | p = self.dirstate.parents()[0] | |
|
1010 |
|
|
|
1011 |
m = self. |
|
|
1012 | if not wlock: | |
|
1013 | wlock = self.wlock() | |
|
1014 | for f in list: | |
|
1015 | if self.dirstate[f] != 'r': | |
|
1016 | self.ui.warn("%s not removed!\n" % f) | |
|
1017 | else: | |
|
1018 | t = self.file(f).read(m[f]) | |
|
1019 |
self. |
|
|
1020 |
self. |
|
|
1029 | try: | |
|
1030 | p = self.dirstate.parents()[0] | |
|
1031 | mn = self.changelog.read(p)[0] | |
|
1032 | m = self.manifest.read(mn) | |
|
1033 | if not wlock: | |
|
1034 | wlock = self.wlock() | |
|
1035 | for f in list: | |
|
1036 | if self.dirstate[f] != 'r': | |
|
1037 | self.ui.warn("%s not removed!\n" % f) | |
|
1038 | else: | |
|
1039 | t = self.file(f).read(m[f]) | |
|
1040 | self.wwrite(f, t, m.flags(f)) | |
|
1041 | self.dirstate.normal(f) | |
|
1042 | finally: | |
|
1043 | del wlock | |
|
1021 | 1044 | |
|
1022 | 1045 | def copy(self, source, dest, wlock=None): |
|
1023 | p = self.wjoin(dest) | |
|
1024 | if not (os.path.exists(p) or os.path.islink(p)): | |
|
1025 | self.ui.warn(_("%s does not exist!\n") % dest) | |
|
1026 | elif not (os.path.isfile(p) or os.path.islink(p)): | |
|
1027 | self.ui.warn(_("copy failed: %s is not a file or a " | |
|
1028 | "symbolic link\n") % dest) | |
|
1029 | else: | |
|
1030 |
|
|
|
1031 |
wlock |
|
|
1032 | if dest not in self.dirstate: | |
|
1033 |
self.dirstate |
|
|
1034 |
self.dirstate. |
|
|
1046 | try: | |
|
1047 | p = self.wjoin(dest) | |
|
1048 | if not (os.path.exists(p) or os.path.islink(p)): | |
|
1049 | self.ui.warn(_("%s does not exist!\n") % dest) | |
|
1050 | elif not (os.path.isfile(p) or os.path.islink(p)): | |
|
1051 | self.ui.warn(_("copy failed: %s is not a file or a " | |
|
1052 | "symbolic link\n") % dest) | |
|
1053 | else: | |
|
1054 | if not wlock: | |
|
1055 | wlock = self.wlock() | |
|
1056 | if dest not in self.dirstate: | |
|
1057 | self.dirstate.add(dest) | |
|
1058 | self.dirstate.copy(source, dest) | |
|
1059 | finally: | |
|
1060 | del wlock | |
|
1035 | 1061 | |
|
1036 | 1062 | def heads(self, start=None): |
|
1037 | 1063 | heads = self.changelog.heads(start) |
@@ -1309,12 +1335,9 b' class localrepository(repo.repository):' | |||
|
1309 | 1335 | return subset |
|
1310 | 1336 | |
|
1311 | 1337 | def pull(self, remote, heads=None, force=False, lock=None): |
|
1312 | mylock = False | |
|
1313 | if not lock: | |
|
1314 | lock = self.lock() | |
|
1315 | mylock = True | |
|
1316 | ||
|
1317 | 1338 | try: |
|
1339 | if not lock: | |
|
1340 | lock = self.lock() | |
|
1318 | 1341 | fetch = self.findincoming(remote, force=force) |
|
1319 | 1342 | if fetch == [nullid]: |
|
1320 | 1343 | self.ui.status(_("requesting all changes\n")) |
@@ -1331,8 +1354,7 b' class localrepository(repo.repository):' | |||
|
1331 | 1354 | cg = remote.changegroupsubset(fetch, heads, 'pull') |
|
1332 | 1355 | return self.addchangegroup(cg, 'pull', remote.url()) |
|
1333 | 1356 | finally: |
|
1334 |
|
|
|
1335 | lock.release() | |
|
1357 | del lock | |
|
1336 | 1358 | |
|
1337 | 1359 | def push(self, remote, force=False, revs=None): |
|
1338 | 1360 | # there are two ways to push to remote repo: |
@@ -1405,12 +1427,14 b' class localrepository(repo.repository):' | |||
|
1405 | 1427 | |
|
1406 | 1428 | def push_addchangegroup(self, remote, force, revs): |
|
1407 | 1429 | lock = remote.lock() |
|
1408 | ||
|
1409 | ret = self.prepush(remote, force, revs) | |
|
1410 | if ret[0] is not None: | |
|
1411 | cg, remote_heads = ret | |
|
1412 | return remote.addchangegroup(cg, 'push', self.url()) | |
|
1413 | return ret[1] | |
|
1430 | try: | |
|
1431 | ret = self.prepush(remote, force, revs) | |
|
1432 | if ret[0] is not None: | |
|
1433 | cg, remote_heads = ret | |
|
1434 | return remote.addchangegroup(cg, 'push', self.url()) | |
|
1435 | return ret[1] | |
|
1436 | finally: | |
|
1437 | del lock | |
|
1414 | 1438 | |
|
1415 | 1439 | def push_unbundle(self, remote, force, revs): |
|
1416 | 1440 | # local repo finds heads on server, finds out what revs it |
@@ -1794,65 +1818,67 b' class localrepository(repo.repository):' | |||
|
1794 | 1818 | |
|
1795 | 1819 | changesets = files = revisions = 0 |
|
1796 | 1820 | |
|
1797 | tr = self.transaction() | |
|
1798 | ||
|
1799 | 1821 | # write changelog data to temp files so concurrent readers will not see |
|
1800 | 1822 | # inconsistent view |
|
1801 | 1823 | cl = self.changelog |
|
1802 | 1824 | cl.delayupdate() |
|
1803 | 1825 | oldheads = len(cl.heads()) |
|
1804 | 1826 | |
|
1805 | # pull off the changeset group | |
|
1806 | self.ui.status(_("adding changesets\n")) | |
|
1807 | cor = cl.count() - 1 | |
|
1808 | chunkiter = changegroup.chunkiter(source) | |
|
1809 | if cl.addgroup(chunkiter, csmap, tr, 1) is None: | |
|
1810 | raise util.Abort(_("received changelog group is empty")) | |
|
1811 | cnr = cl.count() - 1 | |
|
1812 | changesets = cnr - cor | |
|
1827 | tr = self.transaction() | |
|
1828 | try: | |
|
1829 | # pull off the changeset group | |
|
1830 | self.ui.status(_("adding changesets\n")) | |
|
1831 | cor = cl.count() - 1 | |
|
1832 | chunkiter = changegroup.chunkiter(source) | |
|
1833 | if cl.addgroup(chunkiter, csmap, tr, 1) is None: | |
|
1834 | raise util.Abort(_("received changelog group is empty")) | |
|
1835 | cnr = cl.count() - 1 | |
|
1836 | changesets = cnr - cor | |
|
1813 | 1837 | |
|
1814 | # pull off the manifest group | |
|
1815 | self.ui.status(_("adding manifests\n")) | |
|
1816 | chunkiter = changegroup.chunkiter(source) | |
|
1817 | # no need to check for empty manifest group here: | |
|
1818 | # if the result of the merge of 1 and 2 is the same in 3 and 4, | |
|
1819 | # no new manifest will be created and the manifest group will | |
|
1820 | # be empty during the pull | |
|
1821 | self.manifest.addgroup(chunkiter, revmap, tr) | |
|
1838 | # pull off the manifest group | |
|
1839 | self.ui.status(_("adding manifests\n")) | |
|
1840 | chunkiter = changegroup.chunkiter(source) | |
|
1841 | # no need to check for empty manifest group here: | |
|
1842 | # if the result of the merge of 1 and 2 is the same in 3 and 4, | |
|
1843 | # no new manifest will be created and the manifest group will | |
|
1844 | # be empty during the pull | |
|
1845 | self.manifest.addgroup(chunkiter, revmap, tr) | |
|
1822 | 1846 | |
|
1823 | # process the files | |
|
1824 | self.ui.status(_("adding file changes\n")) | |
|
1825 | while 1: | |
|
1826 | f = changegroup.getchunk(source) | |
|
1827 | if not f: | |
|
1828 | break | |
|
1829 | self.ui.debug(_("adding %s revisions\n") % f) | |
|
1830 | fl = self.file(f) | |
|
1831 | o = fl.count() | |
|
1832 | chunkiter = changegroup.chunkiter(source) | |
|
1833 | if fl.addgroup(chunkiter, revmap, tr) is None: | |
|
1834 | raise util.Abort(_("received file revlog group is empty")) | |
|
1835 | revisions += fl.count() - o | |
|
1836 | files += 1 | |
|
1847 | # process the files | |
|
1848 | self.ui.status(_("adding file changes\n")) | |
|
1849 | while 1: | |
|
1850 | f = changegroup.getchunk(source) | |
|
1851 | if not f: | |
|
1852 | break | |
|
1853 | self.ui.debug(_("adding %s revisions\n") % f) | |
|
1854 | fl = self.file(f) | |
|
1855 | o = fl.count() | |
|
1856 | chunkiter = changegroup.chunkiter(source) | |
|
1857 | if fl.addgroup(chunkiter, revmap, tr) is None: | |
|
1858 | raise util.Abort(_("received file revlog group is empty")) | |
|
1859 | revisions += fl.count() - o | |
|
1860 | files += 1 | |
|
1861 | ||
|
1862 | # make changelog see real files again | |
|
1863 | cl.finalize(tr) | |
|
1837 | 1864 | |
|
1838 | # make changelog see real files again | |
|
1839 | cl.finalize(tr) | |
|
1865 | newheads = len(self.changelog.heads()) | |
|
1866 | heads = "" | |
|
1867 | if oldheads and newheads != oldheads: | |
|
1868 | heads = _(" (%+d heads)") % (newheads - oldheads) | |
|
1840 | 1869 | |
|
1841 | newheads = len(self.changelog.heads()) | |
|
1842 | heads = "" | |
|
1843 | if oldheads and newheads != oldheads: | |
|
1844 | heads = _(" (%+d heads)") % (newheads - oldheads) | |
|
1870 | self.ui.status(_("added %d changesets" | |
|
1871 | " with %d changes to %d files%s\n") | |
|
1872 | % (changesets, revisions, files, heads)) | |
|
1845 | 1873 | |
|
1846 | self.ui.status(_("added %d changesets" | |
|
1847 | " with %d changes to %d files%s\n") | |
|
1848 | % (changesets, revisions, files, heads)) | |
|
1874 | if changesets > 0: | |
|
1875 | self.hook('pretxnchangegroup', throw=True, | |
|
1876 | node=hex(self.changelog.node(cor+1)), source=srctype, | |
|
1877 | url=url) | |
|
1849 | 1878 | |
|
1850 | if changesets > 0: | |
|
1851 | self.hook('pretxnchangegroup', throw=True, | |
|
1852 | node=hex(self.changelog.node(cor+1)), source=srctype, | |
|
1853 | url=url) | |
|
1854 | ||
|
1855 | tr.close() | |
|
1879 | tr.close() | |
|
1880 | finally: | |
|
1881 | del tr | |
|
1856 | 1882 | |
|
1857 | 1883 | if changesets > 0: |
|
1858 | 1884 | self.hook("changegroup", node=hex(self.changelog.node(cor+1)), |
@@ -506,65 +506,67 b' def update(repo, node, branchmerge, forc' | |||
|
506 | 506 | wlock = working dir lock, if already held |
|
507 | 507 | """ |
|
508 | 508 | |
|
509 | if not wlock: | |
|
510 | wlock = repo.wlock() | |
|
509 | try: | |
|
510 | if not wlock: | |
|
511 | wlock = repo.wlock() | |
|
511 | 512 | |
|
512 | wc = repo.workingctx() | |
|
513 | if node is None: | |
|
514 | # tip of current branch | |
|
515 | try: | |
|
516 | node = repo.branchtags()[wc.branch()] | |
|
517 | except KeyError: | |
|
518 | raise util.Abort(_("branch %s not found") % wc.branch()) | |
|
519 | overwrite = force and not branchmerge | |
|
520 | forcemerge = force and branchmerge | |
|
521 | pl = wc.parents() | |
|
522 | p1, p2 = pl[0], repo.changectx(node) | |
|
523 | pa = p1.ancestor(p2) | |
|
524 | fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2) | |
|
525 | fastforward = False | |
|
513 | wc = repo.workingctx() | |
|
514 | if node is None: | |
|
515 | # tip of current branch | |
|
516 | try: | |
|
517 | node = repo.branchtags()[wc.branch()] | |
|
518 | except KeyError: | |
|
519 | raise util.Abort(_("branch %s not found") % wc.branch()) | |
|
520 | overwrite = force and not branchmerge | |
|
521 | forcemerge = force and branchmerge | |
|
522 | pl = wc.parents() | |
|
523 | p1, p2 = pl[0], repo.changectx(node) | |
|
524 | pa = p1.ancestor(p2) | |
|
525 | fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2) | |
|
526 | fastforward = False | |
|
526 | 527 | |
|
527 | ### check phase | |
|
528 | if not overwrite and len(pl) > 1: | |
|
529 | raise util.Abort(_("outstanding uncommitted merges")) | |
|
530 | if pa == p1 or pa == p2: # is there a linear path from p1 to p2? | |
|
531 | if branchmerge: | |
|
532 | if p1.branch() != p2.branch() and pa != p2: | |
|
533 | fastforward = True | |
|
534 | else: | |
|
535 | raise util.Abort(_("there is nothing to merge, just use " | |
|
536 | "'hg update' or look at 'hg heads'")) | |
|
537 | elif not (overwrite or branchmerge): | |
|
538 | raise util.Abort(_("update spans branches, use 'hg merge' " | |
|
539 | "or 'hg update -C' to lose changes")) | |
|
540 | if branchmerge and not forcemerge: | |
|
541 | if wc.files(): | |
|
542 | raise util.Abort(_("outstanding uncommitted changes")) | |
|
528 | ### check phase | |
|
529 | if not overwrite and len(pl) > 1: | |
|
530 | raise util.Abort(_("outstanding uncommitted merges")) | |
|
531 | if pa == p1 or pa == p2: # is there a linear path from p1 to p2? | |
|
532 | if branchmerge: | |
|
533 | if p1.branch() != p2.branch() and pa != p2: | |
|
534 | fastforward = True | |
|
535 | else: | |
|
536 | raise util.Abort(_("there is nothing to merge, just use " | |
|
537 | "'hg update' or look at 'hg heads'")) | |
|
538 | elif not (overwrite or branchmerge): | |
|
539 | raise util.Abort(_("update spans branches, use 'hg merge' " | |
|
540 | "or 'hg update -C' to lose changes")) | |
|
541 | if branchmerge and not forcemerge: | |
|
542 | if wc.files(): | |
|
543 | raise util.Abort(_("outstanding uncommitted changes")) | |
|
543 | 544 | |
|
544 | ### calculate phase | |
|
545 | action = [] | |
|
546 | if not force: | |
|
547 | checkunknown(wc, p2) | |
|
548 | if not util.checkfolding(repo.path): | |
|
549 | checkcollision(p2) | |
|
550 | if not branchmerge: | |
|
551 | action += forgetremoved(wc, p2) | |
|
552 | action += manifestmerge(repo, wc, p2, pa, overwrite, partial) | |
|
545 | ### calculate phase | |
|
546 | action = [] | |
|
547 | if not force: | |
|
548 | checkunknown(wc, p2) | |
|
549 | if not util.checkfolding(repo.path): | |
|
550 | checkcollision(p2) | |
|
551 | if not branchmerge: | |
|
552 | action += forgetremoved(wc, p2) | |
|
553 | action += manifestmerge(repo, wc, p2, pa, overwrite, partial) | |
|
553 | 554 | |
|
554 | ### apply phase | |
|
555 | if not branchmerge: # just jump to the new rev | |
|
556 | fp1, fp2, xp1, xp2 = fp2, nullid, xp2, '' | |
|
557 | if not partial: | |
|
558 | repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2) | |
|
555 | ### apply phase | |
|
556 | if not branchmerge: # just jump to the new rev | |
|
557 | fp1, fp2, xp1, xp2 = fp2, nullid, xp2, '' | |
|
558 | if not partial: | |
|
559 | repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2) | |
|
559 | 560 | |
|
560 | stats = applyupdates(repo, action, wc, p2) | |
|
561 | stats = applyupdates(repo, action, wc, p2) | |
|
561 | 562 | |
|
562 | if not partial: | |
|
563 | recordupdates(repo, action, branchmerge) | |
|
564 | repo.dirstate.setparents(fp1, fp2) | |
|
565 | if not branchmerge and not fastforward: | |
|
566 | repo.dirstate.setbranch(p2.branch()) | |
|
567 | repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3]) | |
|
563 | if not partial: | |
|
564 | recordupdates(repo, action, branchmerge) | |
|
565 | repo.dirstate.setparents(fp1, fp2) | |
|
566 | if not branchmerge and not fastforward: | |
|
567 | repo.dirstate.setbranch(p2.branch()) | |
|
568 | repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3]) | |
|
568 | 569 | |
|
569 | return stats | |
|
570 | ||
|
570 | return stats | |
|
571 | finally: | |
|
572 | del wlock |
@@ -66,22 +66,25 b' def stream_out(repo, fileobj, untrusted=' | |||
|
66 | 66 | |
|
67 | 67 | # get consistent snapshot of repo. lock during scan so lock not |
|
68 | 68 | # needed while we stream, and commits can happen. |
|
69 | lock = None | |
|
69 | 70 | try: |
|
70 | repolock = repo.lock() | |
|
71 | except (lock.LockHeld, lock.LockUnavailable), inst: | |
|
72 | repo.ui.warn('locking the repository failed: %s\n' % (inst,)) | |
|
73 | fileobj.write('2\n') | |
|
74 | return | |
|
71 | try: | |
|
72 | repolock = repo.lock() | |
|
73 | except (lock.LockHeld, lock.LockUnavailable), inst: | |
|
74 | repo.ui.warn('locking the repository failed: %s\n' % (inst,)) | |
|
75 | fileobj.write('2\n') | |
|
76 | return | |
|
75 | 77 | |
|
76 | fileobj.write('0\n') | |
|
77 | repo.ui.debug('scanning\n') | |
|
78 | entries = [] | |
|
79 | total_bytes = 0 | |
|
80 | for name, size in walkrepo(repo.spath): | |
|
81 | name = repo.decodefn(util.pconvert(name)) | |
|
82 | entries.append((name, size)) | |
|
83 | total_bytes += size | |
|
84 | repolock.release() | |
|
78 | fileobj.write('0\n') | |
|
79 | repo.ui.debug('scanning\n') | |
|
80 | entries = [] | |
|
81 | total_bytes = 0 | |
|
82 | for name, size in walkrepo(repo.spath): | |
|
83 | name = repo.decodefn(util.pconvert(name)) | |
|
84 | entries.append((name, size)) | |
|
85 | total_bytes += size | |
|
86 | finally: | |
|
87 | del repolock | |
|
85 | 88 | |
|
86 | 89 | repo.ui.debug('%d files, %d bytes to transfer\n' % |
|
87 | 90 | (len(entries), total_bytes)) |
@@ -10,6 +10,13 b' from i18n import _' | |||
|
10 | 10 | import revlog, mdiff |
|
11 | 11 | |
|
12 | 12 | def verify(repo): |
|
13 | lock = repo.lock() | |
|
14 | try: | |
|
15 | return _verify(repo) | |
|
16 | finally: | |
|
17 | del lock | |
|
18 | ||
|
19 | def _verify(repo): | |
|
13 | 20 | filelinkrevs = {} |
|
14 | 21 | filenodes = {} |
|
15 | 22 | changesets = revisions = files = 0 |
@@ -17,8 +24,6 b' def verify(repo):' | |||
|
17 | 24 | warnings = [0] |
|
18 | 25 | neededmanifests = {} |
|
19 | 26 | |
|
20 | lock = repo.lock() | |
|
21 | ||
|
22 | 27 | def err(msg): |
|
23 | 28 | repo.ui.warn(msg + "\n") |
|
24 | 29 | errors[0] += 1 |
General Comments 0
You need to be logged in to leave comments.
Login now