678 |
678 |
679 def _wcrev(self): |
679 def _wcrev(self): |
680 return self._wcrevs()[0] |
680 return self._wcrevs()[0] |
681 |
681 |
682 def _wcchanged(self): |
682 def _wcchanged(self): |
683 """Return (changes, extchanges) where changes is True |
683 """Return (changes, extchanges, missing) where changes is True |
684 if the working directory was changed, and extchanges is |
684 if the working directory was changed, extchanges is |
685 True if any of these changes concern an external entry. |
685 True if any of these changes concern an external entry and missing |
|
686 is True if any change is a missing entry. |
686 """ |
687 """ |
687 output, err = self._svncommand(['status', '--xml']) |
688 output, err = self._svncommand(['status', '--xml']) |
688 externals, changes = [], [] |
689 externals, changes, missing = [], [], [] |
689 doc = xml.dom.minidom.parseString(output) |
690 doc = xml.dom.minidom.parseString(output) |
690 for e in doc.getElementsByTagName('entry'): |
691 for e in doc.getElementsByTagName('entry'): |
691 s = e.getElementsByTagName('wc-status') |
692 s = e.getElementsByTagName('wc-status') |
692 if not s: |
693 if not s: |
693 continue |
694 continue |
694 item = s[0].getAttribute('item') |
695 item = s[0].getAttribute('item') |
695 props = s[0].getAttribute('props') |
696 props = s[0].getAttribute('props') |
696 path = e.getAttribute('path') |
697 path = e.getAttribute('path') |
697 if item == 'external': |
698 if item == 'external': |
698 externals.append(path) |
699 externals.append(path) |
|
700 elif item == 'missing': |
|
701 missing.append(path) |
699 if (item not in ('', 'normal', 'unversioned', 'external') |
702 if (item not in ('', 'normal', 'unversioned', 'external') |
700 or props not in ('', 'none', 'normal')): |
703 or props not in ('', 'none', 'normal')): |
701 changes.append(path) |
704 changes.append(path) |
702 for path in changes: |
705 for path in changes: |
703 for ext in externals: |
706 for ext in externals: |
704 if path == ext or path.startswith(ext + os.sep): |
707 if path == ext or path.startswith(ext + os.sep): |
705 return True, True |
708 return True, True, bool(missing) |
706 return bool(changes), False |
709 return bool(changes), False, bool(missing) |
707 |
710 |
708 def dirty(self, ignoreupdate=False): |
711 def dirty(self, ignoreupdate=False): |
709 if not self._wcchanged()[0]: |
712 if not self._wcchanged()[0]: |
710 if self._state[1] in self._wcrevs() or ignoreupdate: |
713 if self._state[1] in self._wcrevs() or ignoreupdate: |
711 return False |
714 return False |
714 def basestate(self): |
717 def basestate(self): |
715 return self._wcrev() |
718 return self._wcrev() |
716 |
719 |
717 def commit(self, text, user, date): |
720 def commit(self, text, user, date): |
718 # user and date are out of our hands since svn is centralized |
721 # user and date are out of our hands since svn is centralized |
719 changed, extchanged = self._wcchanged() |
722 changed, extchanged, missing = self._wcchanged() |
720 if not changed: |
723 if not changed: |
721 return self._wcrev() |
724 return self._wcrev() |
722 if extchanged: |
725 if extchanged: |
723 # Do not try to commit externals |
726 # Do not try to commit externals |
724 raise util.Abort(_('cannot commit svn externals')) |
727 raise util.Abort(_('cannot commit svn externals')) |
|
728 if missing: |
|
729 # svn can commit with missing entries but aborting like hg |
|
730 # seems a better approach. |
|
731 raise util.Abort(_('cannot commit missing svn entries')) |
725 commitinfo, err = self._svncommand(['commit', '-m', text]) |
732 commitinfo, err = self._svncommand(['commit', '-m', text]) |
726 self._ui.status(commitinfo) |
733 self._ui.status(commitinfo) |
727 newrev = re.search('Committed revision ([0-9]+).', commitinfo) |
734 newrev = re.search('Committed revision ([0-9]+).', commitinfo) |
728 if not newrev: |
735 if not newrev: |
729 if not commitinfo.strip(): |
736 if not commitinfo.strip(): |
771 # update to a directory which has since been deleted and recreated. |
778 # update to a directory which has since been deleted and recreated. |
772 args.append('%s@%s' % (state[0], state[1])) |
779 args.append('%s@%s' % (state[0], state[1])) |
773 status, err = self._svncommand(args, failok=True) |
780 status, err = self._svncommand(args, failok=True) |
774 if not re.search('Checked out revision [0-9]+.', status): |
781 if not re.search('Checked out revision [0-9]+.', status): |
775 if ('is already a working copy for a different URL' in err |
782 if ('is already a working copy for a different URL' in err |
776 and (self._wcchanged() == (False, False))): |
783 and (self._wcchanged()[:2] == (False, False))): |
777 # obstructed but clean working copy, so just blow it away. |
784 # obstructed but clean working copy, so just blow it away. |
778 self.remove() |
785 self.remove() |
779 self.get(state, overwrite=False) |
786 self.get(state, overwrite=False) |
780 return |
787 return |
781 raise util.Abort((status or err).splitlines()[-1]) |
788 raise util.Abort((status or err).splitlines()[-1]) |