1 # -*- encoding: utf-8 -*-
4 log = logging.getLogger('ral.mercurial')
6 __author__ = "Ćukasz Rekucki"
7 __date__ = "$2009-09-25 09:35:06$"
8 __doc__ = "Module documentation."
11 import mercurial.error
15 log = logging.getLogger('wlrepo.document')
17 class MercurialDocument(wlrepo.Document):
19 def data(self, entry):
20 path = self._library._sanitize_string(self.id + u'.' + entry)
22 return self._library._filectx(path, \
23 self._revision.hgrev()).data().decode('utf-8')
24 except mercurial.error.LookupError, e:
25 fl = [x.decode('utf-8') for x in self._revision._changectx]
26 raise wlrepo.EntryNotFound(self._revision, path.decode('utf-8'), fl)
28 def quickwrite(self, entry, data, msg, user=None):
29 user = user or self.owner
31 if isinstance(data, unicode):
32 data = data.encode('utf-8')
34 user = self._library._sanitize_string(user)
35 msg = self._library._sanitize_string(msg)
36 entry = self._library._sanitize_string(entry)
39 raise ValueError("Can't determine user.")
42 f = l._fileopen(r(entry), "w+")
47 return self.invoke_and_commit(write, lambda d: (msg, \
48 self._library._sanitize_string(self.owner)) )
50 def invoke_and_commit(self, ops, commit_info):
51 lock = self._library.lock()
53 self._library._checkout(self._revision.hgrev())
55 def entry_path(entry):
56 return self._library._sanitize_string(self.id + u'.' + entry)
58 ops(self._library, entry_path)
59 message, user = commit_info(self)
61 message = self._library._sanitize_string(message)
62 user = self._library._sanitize_string(user)
64 self._library._commit(message, user)
66 return self._library.document(docid=self.id, user=user)
68 # rollback the last commit
69 self._library._rollback()
74 # def commit(self, message, user):
75 # """Make a new commit."""
76 # self.invoke_and_commit(message, user, lambda *a: True)
79 return self._revision.user_name is None
82 return (self == self.latest())
88 return self._library.document(docid=self.id)
91 return self._library.document(docid=self.id, user=self.owner)
94 fullid = self._library.fulldocid(self.id, user)
96 def take_action(library, resolve):
98 library._set_branchname(fullid)
100 if not self._library.has_revision(fullid):
101 log.info("Checking out document %s" % fullid)
103 self.invoke_and_commit(take_action, \
104 lambda d: ("$AUTO$ File checkout.", user) )
106 return self._library.document_for_revision(fullid)
108 def up_to_date(self):
112 shared = self.shared()
114 if shared.ancestorof(self):
117 if shared.has_parent_from(self):
122 def update(self, user):
123 """Update parts of the document."""
124 lock = self.library.lock()
127 # main revision of the document
130 # check for children in this branch
131 if self._revision.has_children(limit_branch=True):
132 raise wlrepo.UpdateException("Revision %s has children." % self.revision)
134 shared = self.shared()
140 # we carry the latest version
141 if shared.ancestorof(self):
150 if self.parentof(shared):
158 # This is ok (s - shared, S - self)
160 if self._revision.merge_with(shared._revision, user=user,\
161 message="$AUTO$ Personal branch update."):
164 raise wlrepo.UpdateException("Merge failed.")
169 def would_share(self):
171 return False, "Main version is always shared"
173 shared = self.shared()
175 # we just did this - move on
176 if self.parentof(shared):
177 return False, "Document has been recetly shared - no changes"
185 # Situation above is ok - what we don't want, is:
192 # We want to prevent stuff like this.
193 if self.parent().parentof(shared) and shared.parentof(self):
194 return False, "Preventing zig-zag"
196 return True, "All ok"
198 def share(self, message):
199 lock = self.library.lock()
201 # check if the document is in "updated" state
202 if not self.up_to_date():
203 raise wlrepo.OutdatedException("You must update your document before share.")
205 # now check if there is anything to do
206 need_work, info = self.would_share()
220 shared = self.shared()
223 success = shared._revision.merge_with(self._revision, user=self.owner, message=message)
225 raise wlrepo.LibraryException("Merge failed.")
227 return shared.latest()
229 raise wlrepo.LibraryException( repr(e) )
234 def has_conflict_marks(self):
235 return re.search("^(?:<<<<<<< .*|=======|>>>>>>> .*)$", self.data('xml'), re.MULTILINE)
237 def __unicode__(self):
238 return u"Document(%s:%s)" % (self.id, self.owner)
241 return self.__unicode__().encode('utf-8')
243 def __eq__(self, other):
244 return (self._revision == other._revision)