X-Git-Url: https://git.mdrn.pl/redakcja.git/blobdiff_plain/a13dbb38931d9248376d92016d1c457d5a4adbde..c6b7810b77a7b84da1114ddfd424357496bcab9f:/lib/wlrepo/mercurial_backend/document.py?ds=sidebyside diff --git a/lib/wlrepo/mercurial_backend/document.py b/lib/wlrepo/mercurial_backend/document.py index 6cf8a5bf..0883d99b 100644 --- a/lib/wlrepo/mercurial_backend/document.py +++ b/lib/wlrepo/mercurial_backend/document.py @@ -1,17 +1,29 @@ # -*- encoding: utf-8 -*- +import logging +log = logging.getLogger('ral.mercurial') + __author__ = "Łukasz Rekucki" __date__ = "$2009-09-25 09:35:06$" __doc__ = "Module documentation." import wlrepo +import mercurial.error +import re + +import logging +log = logging.getLogger('wlrepo.document') class MercurialDocument(wlrepo.Document): def data(self, entry): - path = self._revision._docname + '.' + entry - return self._library._filectx(path, \ - self._revision.hgrev()).data() + path = self._library._sanitize_string(self.id + u'.' + entry) + try: + return self._library._filectx(path, \ + self._revision.hgrev()).data().decode('utf-8') + except mercurial.error.LookupError, e: + fl = [x.decode('utf-8') for x in self._revision._changectx] + raise wlrepo.EntryNotFound(self._revision, path.decode('utf-8'), fl) def quickwrite(self, entry, data, msg, user=None): user = user or self.owner @@ -32,25 +44,29 @@ class MercurialDocument(wlrepo.Document): f.close() l._fileadd(r(entry)) - return self.invoke_and_commit(write, lambda d: (msg, user)) + return self.invoke_and_commit(write, lambda d: (msg, \ + self._library._sanitize_string(self.owner)) ) - def invoke_and_commit(self, ops, - before_commit, rollback=False): + def invoke_and_commit(self, ops, commit_info): lock = self._library.lock() try: self._library._checkout(self._revision.hgrev()) def entry_path(entry): - return self.id + '.' + entry + return self._library._sanitize_string(self.id + u'.' + entry) ops(self._library, entry_path) - message, user = before_commit(self) + message, user = commit_info(self) + + message = self._library._sanitize_string(message) + user = self._library._sanitize_string(user) + self._library._commit(message, user) try: return self._library.document(docid=self.id, user=user) except Exception, e: # rollback the last commit - self._library.rollback() + self._library._rollback() raise e finally: lock.release() @@ -60,7 +76,10 @@ class MercurialDocument(wlrepo.Document): # self.invoke_and_commit(message, user, lambda *a: True) def ismain(self): - return self._revision.user_name() is None + return self._revision.user_name is None + + def islatest(self): + return (self == self.latest()) def shared(self): if self.ismain(): @@ -76,13 +95,20 @@ class MercurialDocument(wlrepo.Document): def take_action(library, resolve): # branch from latest - library._create_branch(fullid, parent=self._revision) + library._set_branchname(fullid) if not self._library.has_revision(fullid): + log.info("Checking out document %s" % fullid) + self.invoke_and_commit(take_action, \ lambda d: ("$AUTO$ File checkout.", user) ) return self._library.document_for_rev(fullid) + + def up_to_date(self): + return self.ismain() or (\ + self.shared().ancestorof(self) ) + def update(self, user): """Update parts of the document.""" @@ -93,15 +119,20 @@ class MercurialDocument(wlrepo.Document): return (True, False) if self._revision.has_children(): + log.info('Update failed: has children.') # can't update non-latest revision return (False, False) sv = self.shared() - - if not sv.ancestorof(self) and not self.parentof(sv): - return self._revision.merge_with(sv._revision, user=user) - return (False, False) + if self.parentof(sv): + return (True, False) + + if sv.ancestorof(self): + return (True, False) + + return self._revision.merge_with(sv._revision, user=user, + message="$AUTO$ Personal branch update.") finally: lock.release() @@ -109,9 +140,9 @@ class MercurialDocument(wlrepo.Document): lock = self.library.lock() try: if self.ismain(): - return (True, False) # always shared + return False # always shared - user = self._revision.user_name() + user = self._revision.user_name main = self.shared()._revision local = self._revision @@ -127,26 +158,17 @@ class MercurialDocument(wlrepo.Document): # so we don't need to update yet again, but we need to # merge down to default branch, even if there was # no commit's since last update - + # + # This is actually the only good case! if main.ancestorof(local): - print "case 1" - success, changed = main.merge_with(local, user=user, message=message) + success, changed = main.merge_with(local, user=user, message=message) + + if not success: + raise LibraryException("Merge failed.") + + return changed + # Case 2: - # - # main * * local - # |\ | - # | \| - # | * - # | | - # - # Default has no changes, to update from this branch - # since the last merge of local to default. - elif local.has_common_ancestor(main): - print "case 2" - if not local.parentof(main): - success, changed = main.merge_with(local, user=user, message=message) - - # Case 3: # main * # | # * <- this case overlaps with previos one @@ -158,35 +180,27 @@ class MercurialDocument(wlrepo.Document): # There was a recent merge to the defaul branch and # no changes to local branch recently. # - # Use the fact, that user is prepared to see changes, to - # update his branch if there are any - elif local.ancestorof(main): - print "case 3" - if not local.parentof(main): - success, changed = local.merge_with(main, user=user, \ - message='$AUTO$ Local branch update during share.') - - else: - print "case 4" - success, changed = local.merge_with(main, user=user, \ - message='$AUTO$ Local branch update during share.') - - if not success: - return False + # Nothing to do + elif local.ancestorof(main): + return False - if changed: - local = local.latest() - - success, changed = main.merge_with(local, user=user,\ - message=message) - - return success, changed + # In all other cases, the local needs an update + # and possibly conflict resolution, so fail + raise LibraryExcepton("Document not prepared for sharing.") + finally: - lock.release() + lock.release() - def __str__(self): - return u"Document(%s:%s)" % (self.name, self.owner) + def has_conflict_marks(self): + return re.search("^(?:<<<<<<< .*|=======|>>>>>>> .*)$", self.data('xml'), re.MULTILINE) + + def __unicode__(self): + return u"Document(%s:%s)" % (self.id, self.owner) + + def __str__(self): + return self.__unicode__().encode('utf-8') + def __eq__(self, other): - return (self._revision == other._revision) and (self.name == other.name) + return (self._revision == other._revision)