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