Show More
@@ -577,9 +577,136 b' def shrink(ui, repo, *pats, **opts):' | |||||
577 | # 3rd argument sets expansion to False |
|
577 | # 3rd argument sets expansion to False | |
578 | _kwfwrite(ui, repo, False, *pats, **opts) |
|
578 | _kwfwrite(ui, repo, False, *pats, **opts) | |
579 |
|
579 | |||
|
580 | # monkeypatches | |||
|
581 | ||||
|
582 | def kwpatchfile_init(orig, self, ui, gp, backend, store, eolmode=None): | |||
|
583 | '''Monkeypatch/wrap patch.patchfile.__init__ to avoid | |||
|
584 | rejects or conflicts due to expanded keywords in working dir.''' | |||
|
585 | orig(self, ui, gp, backend, store, eolmode) | |||
|
586 | kwt = getattr(getattr(backend, 'repo', None), '_keywordkwt', None) | |||
|
587 | if kwt: | |||
|
588 | # shrink keywords read from working dir | |||
|
589 | self.lines = kwt.shrinklines(self.fname, self.lines) | |||
|
590 | ||||
|
591 | def kwdiff(orig, repo, *args, **kwargs): | |||
|
592 | '''Monkeypatch patch.diff to avoid expansion.''' | |||
|
593 | kwt = getattr(repo, '_keywordkwt', None) | |||
|
594 | if kwt: | |||
|
595 | restrict = kwt.restrict | |||
|
596 | kwt.restrict = True | |||
|
597 | try: | |||
|
598 | for chunk in orig(repo, *args, **kwargs): | |||
|
599 | yield chunk | |||
|
600 | finally: | |||
|
601 | if kwt: | |||
|
602 | kwt.restrict = restrict | |||
|
603 | ||||
|
604 | def kwweb_skip(orig, web, req, tmpl): | |||
|
605 | '''Wraps webcommands.x turning off keyword expansion.''' | |||
|
606 | kwt = getattr(web.repo, '_keywordkwt', None) | |||
|
607 | if kwt: | |||
|
608 | origmatch = kwt.match | |||
|
609 | kwt.match = util.never | |||
|
610 | try: | |||
|
611 | for chunk in orig(web, req, tmpl): | |||
|
612 | yield chunk | |||
|
613 | finally: | |||
|
614 | if kwt: | |||
|
615 | kwt.match = origmatch | |||
|
616 | ||||
|
617 | def kw_amend(orig, ui, repo, commitfunc, old, extra, pats, opts): | |||
|
618 | '''Wraps cmdutil.amend expanding keywords after amend.''' | |||
|
619 | kwt = getattr(repo, '_keywordkwt', None) | |||
|
620 | if kwt is None: | |||
|
621 | return orig(ui, repo, commitfunc, old, extra, pats, opts) | |||
|
622 | with repo.wlock(): | |||
|
623 | kwt.postcommit = True | |||
|
624 | newid = orig(ui, repo, commitfunc, old, extra, pats, opts) | |||
|
625 | if newid != old.node(): | |||
|
626 | ctx = repo[newid] | |||
|
627 | kwt.restrict = True | |||
|
628 | kwt.overwrite(ctx, ctx.files(), False, True) | |||
|
629 | kwt.restrict = False | |||
|
630 | return newid | |||
|
631 | ||||
|
632 | def kw_copy(orig, ui, repo, pats, opts, rename=False): | |||
|
633 | '''Wraps cmdutil.copy so that copy/rename destinations do not | |||
|
634 | contain expanded keywords. | |||
|
635 | Note that the source of a regular file destination may also be a | |||
|
636 | symlink: | |||
|
637 | hg cp sym x -> x is symlink | |||
|
638 | cp sym x; hg cp -A sym x -> x is file (maybe expanded keywords) | |||
|
639 | For the latter we have to follow the symlink to find out whether its | |||
|
640 | target is configured for expansion and we therefore must unexpand the | |||
|
641 | keywords in the destination.''' | |||
|
642 | kwt = getattr(repo, '_keywordkwt', None) | |||
|
643 | if kwt is None: | |||
|
644 | return orig(ui, repo, pats, opts, rename) | |||
|
645 | with repo.wlock(): | |||
|
646 | orig(ui, repo, pats, opts, rename) | |||
|
647 | if opts.get('dry_run'): | |||
|
648 | return | |||
|
649 | wctx = repo[None] | |||
|
650 | cwd = repo.getcwd() | |||
|
651 | ||||
|
652 | def haskwsource(dest): | |||
|
653 | '''Returns true if dest is a regular file and configured for | |||
|
654 | expansion or a symlink which points to a file configured for | |||
|
655 | expansion. ''' | |||
|
656 | source = repo.dirstate.copied(dest) | |||
|
657 | if 'l' in wctx.flags(source): | |||
|
658 | source = pathutil.canonpath(repo.root, cwd, | |||
|
659 | os.path.realpath(source)) | |||
|
660 | return kwt.match(source) | |||
|
661 | ||||
|
662 | candidates = [f for f in repo.dirstate.copies() if | |||
|
663 | 'l' not in wctx.flags(f) and haskwsource(f)] | |||
|
664 | kwt.overwrite(wctx, candidates, False, False) | |||
|
665 | ||||
|
666 | def kw_dorecord(orig, ui, repo, commitfunc, *pats, **opts): | |||
|
667 | '''Wraps record.dorecord expanding keywords after recording.''' | |||
|
668 | kwt = getattr(repo, '_keywordkwt', None) | |||
|
669 | if kwt is None: | |||
|
670 | return orig(ui, repo, commitfunc, *pats, **opts) | |||
|
671 | with repo.wlock(): | |||
|
672 | # record returns 0 even when nothing has changed | |||
|
673 | # therefore compare nodes before and after | |||
|
674 | kwt.postcommit = True | |||
|
675 | ctx = repo['.'] | |||
|
676 | wstatus = ctx.status() | |||
|
677 | ret = orig(ui, repo, commitfunc, *pats, **opts) | |||
|
678 | recctx = repo['.'] | |||
|
679 | if ctx != recctx: | |||
|
680 | modified, added = _preselect(wstatus, recctx.files()) | |||
|
681 | kwt.restrict = False | |||
|
682 | kwt.overwrite(recctx, modified, False, True) | |||
|
683 | kwt.overwrite(recctx, added, False, True, True) | |||
|
684 | kwt.restrict = True | |||
|
685 | return ret | |||
|
686 | ||||
|
687 | def kwfilectx_cmp(orig, self, fctx): | |||
|
688 | if fctx._customcmp: | |||
|
689 | return fctx.cmp(self) | |||
|
690 | kwt = getattr(self._repo, '_keywordkwt', None) | |||
|
691 | if kwt is None: | |||
|
692 | return orig(self, fctx) | |||
|
693 | # keyword affects data size, comparing wdir and filelog size does | |||
|
694 | # not make sense | |||
|
695 | if (fctx._filenode is None and | |||
|
696 | (self._repo._encodefilterpats or | |||
|
697 | kwt.match(fctx.path()) and 'l' not in fctx.flags() or | |||
|
698 | self.size() - 4 == fctx.size()) or | |||
|
699 | self.size() == fctx.size()): | |||
|
700 | return self._filelog.cmp(self._filenode, fctx.data()) | |||
|
701 | return True | |||
580 |
|
702 | |||
581 | def uisetup(ui): |
|
703 | def uisetup(ui): | |
582 |
''' Monkeypatches dispatch._parse to retrieve user command. |
|
704 | ''' Monkeypatches dispatch._parse to retrieve user command. | |
|
705 | Overrides file method to return kwfilelog instead of filelog | |||
|
706 | if file matches user configuration. | |||
|
707 | Wraps commit to overwrite configured files with updated | |||
|
708 | keyword substitutions. | |||
|
709 | Monkeypatches patch and webcommands.''' | |||
583 |
|
710 | |||
584 | def kwdispatch_parse(orig, ui, args): |
|
711 | def kwdispatch_parse(orig, ui, args): | |
585 | '''Monkeypatch dispatch._parse to obtain running hg command.''' |
|
712 | '''Monkeypatch dispatch._parse to obtain running hg command.''' | |
@@ -589,13 +716,17 b' def uisetup(ui):' | |||||
589 |
|
716 | |||
590 | extensions.wrapfunction(dispatch, '_parse', kwdispatch_parse) |
|
717 | extensions.wrapfunction(dispatch, '_parse', kwdispatch_parse) | |
591 |
|
718 | |||
|
719 | extensions.wrapfunction(context.filectx, 'cmp', kwfilectx_cmp) | |||
|
720 | extensions.wrapfunction(patch.patchfile, '__init__', kwpatchfile_init) | |||
|
721 | extensions.wrapfunction(patch, 'diff', kwdiff) | |||
|
722 | extensions.wrapfunction(cmdutil, 'amend', kw_amend) | |||
|
723 | extensions.wrapfunction(cmdutil, 'copy', kw_copy) | |||
|
724 | extensions.wrapfunction(cmdutil, 'dorecord', kw_dorecord) | |||
|
725 | for c in nokwwebcommands.split(): | |||
|
726 | extensions.wrapfunction(webcommands, c, kwweb_skip) | |||
|
727 | ||||
592 | def reposetup(ui, repo): |
|
728 | def reposetup(ui, repo): | |
593 | '''Sets up repo as kwrepo for keyword substitution. |
|
729 | '''Sets up repo as kwrepo for keyword substitution.''' | |
594 | Overrides file method to return kwfilelog instead of filelog |
|
|||
595 | if file matches user configuration. |
|
|||
596 | Wraps commit to overwrite configured files with updated |
|
|||
597 | keyword substitutions. |
|
|||
598 | Monkeypatches patch and webcommands.''' |
|
|||
599 |
|
730 | |||
600 | try: |
|
731 | try: | |
601 | if (not repo.local() or kwtools['hgcmd'] in nokwcommands.split() |
|
732 | if (not repo.local() or kwtools['hgcmd'] in nokwcommands.split() | |
@@ -665,134 +796,3 b' def reposetup(ui, repo):' | |||||
665 |
|
796 | |||
666 | repo.__class__ = kwrepo |
|
797 | repo.__class__ = kwrepo | |
667 | repo._keywordkwt = kwt |
|
798 | repo._keywordkwt = kwt | |
668 |
|
||||
669 | # monkeypatches |
|
|||
670 | def kwpatchfile_init(orig, self, ui, gp, backend, store, eolmode=None): |
|
|||
671 | '''Monkeypatch/wrap patch.patchfile.__init__ to avoid |
|
|||
672 | rejects or conflicts due to expanded keywords in working dir.''' |
|
|||
673 | orig(self, ui, gp, backend, store, eolmode) |
|
|||
674 | kwt = getattr(getattr(backend, 'repo', None), '_keywordkwt', None) |
|
|||
675 | if kwt: |
|
|||
676 | # shrink keywords read from working dir |
|
|||
677 | self.lines = kwt.shrinklines(self.fname, self.lines) |
|
|||
678 |
|
||||
679 | def kwdiff(orig, repo, *args, **kwargs): |
|
|||
680 | '''Monkeypatch patch.diff to avoid expansion.''' |
|
|||
681 | kwt = getattr(repo, '_keywordkwt', None) |
|
|||
682 | if kwt: |
|
|||
683 | restrict = kwt.restrict |
|
|||
684 | kwt.restrict = True |
|
|||
685 | try: |
|
|||
686 | for chunk in orig(repo, *args, **kwargs): |
|
|||
687 | yield chunk |
|
|||
688 | finally: |
|
|||
689 | if kwt: |
|
|||
690 | kwt.restrict = restrict |
|
|||
691 |
|
||||
692 | def kwweb_skip(orig, web, req, tmpl): |
|
|||
693 | '''Wraps webcommands.x turning off keyword expansion.''' |
|
|||
694 | kwt = getattr(web.repo, '_keywordkwt', None) |
|
|||
695 | if kwt: |
|
|||
696 | origmatch = kwt.match |
|
|||
697 | kwt.match = util.never |
|
|||
698 | try: |
|
|||
699 | for chunk in orig(web, req, tmpl): |
|
|||
700 | yield chunk |
|
|||
701 | finally: |
|
|||
702 | if kwt: |
|
|||
703 | kwt.match = origmatch |
|
|||
704 |
|
||||
705 | def kw_amend(orig, ui, repo, commitfunc, old, extra, pats, opts): |
|
|||
706 | '''Wraps cmdutil.amend expanding keywords after amend.''' |
|
|||
707 | kwt = getattr(repo, '_keywordkwt', None) |
|
|||
708 | if kwt is None: |
|
|||
709 | return orig(ui, repo, commitfunc, old, extra, pats, opts) |
|
|||
710 | with repo.wlock(): |
|
|||
711 | kwt.postcommit = True |
|
|||
712 | newid = orig(ui, repo, commitfunc, old, extra, pats, opts) |
|
|||
713 | if newid != old.node(): |
|
|||
714 | ctx = repo[newid] |
|
|||
715 | kwt.restrict = True |
|
|||
716 | kwt.overwrite(ctx, ctx.files(), False, True) |
|
|||
717 | kwt.restrict = False |
|
|||
718 | return newid |
|
|||
719 |
|
||||
720 | def kw_copy(orig, ui, repo, pats, opts, rename=False): |
|
|||
721 | '''Wraps cmdutil.copy so that copy/rename destinations do not |
|
|||
722 | contain expanded keywords. |
|
|||
723 | Note that the source of a regular file destination may also be a |
|
|||
724 | symlink: |
|
|||
725 | hg cp sym x -> x is symlink |
|
|||
726 | cp sym x; hg cp -A sym x -> x is file (maybe expanded keywords) |
|
|||
727 | For the latter we have to follow the symlink to find out whether its |
|
|||
728 | target is configured for expansion and we therefore must unexpand the |
|
|||
729 | keywords in the destination.''' |
|
|||
730 | kwt = getattr(repo, '_keywordkwt', None) |
|
|||
731 | if kwt is None: |
|
|||
732 | return orig(ui, repo, pats, opts, rename) |
|
|||
733 | with repo.wlock(): |
|
|||
734 | orig(ui, repo, pats, opts, rename) |
|
|||
735 | if opts.get('dry_run'): |
|
|||
736 | return |
|
|||
737 | wctx = repo[None] |
|
|||
738 | cwd = repo.getcwd() |
|
|||
739 |
|
||||
740 | def haskwsource(dest): |
|
|||
741 | '''Returns true if dest is a regular file and configured for |
|
|||
742 | expansion or a symlink which points to a file configured for |
|
|||
743 | expansion. ''' |
|
|||
744 | source = repo.dirstate.copied(dest) |
|
|||
745 | if 'l' in wctx.flags(source): |
|
|||
746 | source = pathutil.canonpath(repo.root, cwd, |
|
|||
747 | os.path.realpath(source)) |
|
|||
748 | return kwt.match(source) |
|
|||
749 |
|
||||
750 | candidates = [f for f in repo.dirstate.copies() if |
|
|||
751 | 'l' not in wctx.flags(f) and haskwsource(f)] |
|
|||
752 | kwt.overwrite(wctx, candidates, False, False) |
|
|||
753 |
|
||||
754 | def kw_dorecord(orig, ui, repo, commitfunc, *pats, **opts): |
|
|||
755 | '''Wraps record.dorecord expanding keywords after recording.''' |
|
|||
756 | kwt = getattr(repo, '_keywordkwt', None) |
|
|||
757 | if kwt is None: |
|
|||
758 | return orig(ui, repo, commitfunc, *pats, **opts) |
|
|||
759 | with repo.wlock(): |
|
|||
760 | # record returns 0 even when nothing has changed |
|
|||
761 | # therefore compare nodes before and after |
|
|||
762 | kwt.postcommit = True |
|
|||
763 | ctx = repo['.'] |
|
|||
764 | wstatus = ctx.status() |
|
|||
765 | ret = orig(ui, repo, commitfunc, *pats, **opts) |
|
|||
766 | recctx = repo['.'] |
|
|||
767 | if ctx != recctx: |
|
|||
768 | modified, added = _preselect(wstatus, recctx.files()) |
|
|||
769 | kwt.restrict = False |
|
|||
770 | kwt.overwrite(recctx, modified, False, True) |
|
|||
771 | kwt.overwrite(recctx, added, False, True, True) |
|
|||
772 | kwt.restrict = True |
|
|||
773 | return ret |
|
|||
774 |
|
||||
775 | def kwfilectx_cmp(orig, self, fctx): |
|
|||
776 | if fctx._customcmp: |
|
|||
777 | return fctx.cmp(self) |
|
|||
778 | kwt = getattr(self._repo, '_keywordkwt', None) |
|
|||
779 | if kwt is None: |
|
|||
780 | return orig(self, fctx) |
|
|||
781 | # keyword affects data size, comparing wdir and filelog size does |
|
|||
782 | # not make sense |
|
|||
783 | if (fctx._filenode is None and |
|
|||
784 | (self._repo._encodefilterpats or |
|
|||
785 | kwt.match(fctx.path()) and 'l' not in fctx.flags() or |
|
|||
786 | self.size() - 4 == fctx.size()) or |
|
|||
787 | self.size() == fctx.size()): |
|
|||
788 | return self._filelog.cmp(self._filenode, fctx.data()) |
|
|||
789 | return True |
|
|||
790 |
|
||||
791 | extensions.wrapfunction(context.filectx, 'cmp', kwfilectx_cmp) |
|
|||
792 | extensions.wrapfunction(patch.patchfile, '__init__', kwpatchfile_init) |
|
|||
793 | extensions.wrapfunction(patch, 'diff', kwdiff) |
|
|||
794 | extensions.wrapfunction(cmdutil, 'amend', kw_amend) |
|
|||
795 | extensions.wrapfunction(cmdutil, 'copy', kw_copy) |
|
|||
796 | extensions.wrapfunction(cmdutil, 'dorecord', kw_dorecord) |
|
|||
797 | for c in nokwwebcommands.split(): |
|
|||
798 | extensions.wrapfunction(webcommands, c, kwweb_skip) |
|
General Comments 0
You need to be logged in to leave comments.
Login now