+ mshelf = mdoc.shelf()
+ shelf = self.shelf()
+
+ if not mshelf.ancestorof(shelf) and not shelf.parentof(mshelf):
+ shelf.merge_with(mshelf, user=user)
+
+ return True
+ finally:
+ lock.release()
+
+ def share(self, message):
+ lock = self.library._lock()
+ try:
+ print "sharing from", self._cabinet, self._cabinet.username
+
+ if self._cabinet.ismain():
+ return True # always shared
+
+ if self._cabinet.username is None:
+ raise ValueError("Can only share documents from personal cabinets.")
+
+ user = self._cabinet.username
+
+ main = self.shared().shelf()
+ local = self.shelf()
+
+ no_changes = True
+
+ # Case 1:
+ # * local
+ # |
+ # * <- can also be here!
+ # /|
+ # / |
+ # main * *
+ # | |
+ # The local branch has been recently updated,
+ # 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
+
+ if main.ancestorof(local):
+ main.merge_with(local, user=user, message=message)
+ no_changes = False
+
+ # 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):
+ if not local.parentof(main):
+ main.merge_with(local, user=user, message=message)
+ no_changes = False
+
+ # Case 3:
+ # main *
+ # |
+ # * <- this case overlaps with previos one
+ # |\
+ # | \
+ # | * local
+ # | |
+ #
+ # 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):
+ if not local.parentof(main):
+ local.merge_with(main, user=user, message='Local branch update.')
+ no_changes = False
+ else:
+ local.merge_with(main, user=user, message='Local branch update.')
+
+ self._refresh()
+ local = self.shelf()
+
+ main.merge_with(local, user=user, message=message)
+ finally:
+ lock.release()
+
+ def shared(self):
+ return self.library.main_cabinet.retrieve(self._name)
+
+ def exists(self):
+ return self._cabinet.exists(self._fileid)
+
+ @property
+ def size(self):
+ return self._filectx.size()
+
+ def shelf(self):
+ return MercurialShelf(self.library, self._filectx.node())
+
+ @property
+ def last_modified(self):
+ return self._filectx.date()
+
+ def __str__(self):
+ return u"Document(%s->%s)" % (self._cabinet.name, self._name)
+
+ def __eq__(self, other):
+ return self._filectx == other._filectx
+
+
+
+class MercurialShelf(wlrepo.Shelf):
+
+ def __init__(self, lib, changectx):
+ super(MercurialShelf, self).__init__(lib)
+
+ if isinstance(changectx, str):
+ self._changectx = lib._changectx(changectx)
+ else:
+ self._changectx = changectx
+
+ @property
+ def _rev(self):
+ return self._changectx.node()
+
+ def __str__(self):
+ return self._changectx.hex()
+
+ def __repr__(self):
+ return "MercurialShelf(%s)" % self._changectx.hex()
+
+ def ancestorof(self, other):
+ nodes = list(other._changectx._parents)
+ while nodes[0].node() != nullid:
+ v = nodes.pop(0)
+ if v == self._changectx:
+ return True
+ nodes.extend( v._parents )
+ return False
+
+ def parentof(self, other):
+ return self._changectx in other._changectx._parents
+
+ def has_common_ancestor(self, other):
+ a = self._changectx.ancestor(other._changectx)
+ print a, self._changectx.branch(), a.branch()
+
+ return (a.branch() == self._changectx.branch())
+
+ def merge_with(self, other, user, message):
+ lock = self._library._lock(True)
+ try:
+ self._library._checkout(self._changectx.node())
+ self._library._merge(other._changectx.node())
+ finally:
+ lock.release()
+
+ def __eq__(self, other):
+ return self._changectx.node() == other._changectx.node()
+