From 10fe016074c5af0f8e0464eb3191e868f108a65e Mon Sep 17 00:00:00 2001 From: Lukasz Date: Mon, 26 Oct 2009 06:35:41 -0400 Subject: [PATCH 1/1] Oslabienie warunku na pull. Poprawienie bledu z zapisie, gdy DC byl niepoprawny. --- apps/api/handlers/library_handlers.py | 199 ++++++++++++----------- apps/api/handlers/text_handler.py | 5 +- lib/wlrepo/__init__.py | 3 + lib/wlrepo/mercurial_backend/document.py | 21 ++- 4 files changed, 122 insertions(+), 106 deletions(-) diff --git a/apps/api/handlers/library_handlers.py b/apps/api/handlers/library_handlers.py index 8f8f2bc0..cbd3a0a9 100755 --- a/apps/api/handlers/library_handlers.py +++ b/apps/api/handlers/library_handlers.py @@ -476,114 +476,125 @@ class MergeHandler(BaseHandler): @hglibrary def create(self, request, form, docid, lib): """Create a new document revision from the information provided by user""" - revision = form.cleaned_data['revision'] + try: + revision = form.cleaned_data['revision'] - # fetch the main branch document - doc = lib.document(docid) + # fetch the main branch document + doc = lib.document(docid) - # fetch the base document - user_doc = lib.document_for_revision(revision) - base_doc = user_doc.latest() + # fetch the base document + user_doc = lib.document_for_revision(revision) + base_doc = user_doc.latest() - if base_doc != user_doc: - return response.EntityConflict().django_response({ - "reason": "out-of-date", - "provided": str(user_doc.revision), - "latest": str(base_doc.revision) - }) - - if form.cleaned_data['type'] == 'update': - # update is always performed from the file branch - # to the user branch - user_doc_new = base_doc.update(request.user.username) - - if user_doc_new == user_doc: - return response.SuccessAllOk().django_response({ - "result": "no-op" + if base_doc != user_doc: + return response.EntityConflict().django_response({ + "reason": "out-of-date", + "provided": str(user_doc.revision), + "latest": str(base_doc.revision) }) - - # shared document is the same - doc_new = doc - if form.cleaned_data['type'] == 'share': - if not base_doc.up_to_date(): - return response.BadRequest().django_response({ - "reason": "not-fast-forward", - "message": "You must first update your branch to the latest version." - }) + if form.cleaned_data['type'] == 'update': + # update is always performed from the file branch + # to the user branch + user_doc_new = base_doc.update(request.user.username) - anwser, info = base_doc.would_share() - - if not anwser: - return response.SuccessAllOk().django_response({ - "result": "no-op", "message": info - }) + if user_doc_new == user_doc: + return response.SuccessAllOk().django_response({ + "result": "no-op" + }) - # check for unresolved conflicts - if base_doc.has_conflict_marks(): - return response.BadRequest().django_response({ - "reason": "unresolved-conflicts", - "message": "There are unresolved conflicts in your file. Fix them, and try again." - }) + # shared document is the same + doc_new = doc - if not request.user.has_perm('api.share_document'): - # User is not permitted to make a merge, right away - # So we instead create a pull request in the database - try: - prq, created = PullRequest.objects.get_or_create( - comitter = request.user, - document = docid, - status = "N", - defaults = { - 'source_revision': str(base_doc.revision), - 'comment': form.cleaned_data['message'] or '$AUTO$ Document shared.', - } - ) - - # there can't be 2 pending request from same user - # for the same document - if not created: - prq.source_revision = str(base_doc.revision) - prq.comment = prq.comment + 'u\n\n' + (form.cleaned_data['message'] or u'') - prq.save() - - return response.RequestAccepted().django_response(\ - ticket_status=prq.status, \ - ticket_uri=reverse("pullrequest_view", args=[prq.id]) ) - except IntegrityError: - return response.EntityConflict().django_response({ - 'reason': 'request-already-exist' + if form.cleaned_data['type'] == 'share': + if not base_doc.up_to_date(): + return response.BadRequest().django_response({ + "reason": "not-fast-forward", + "message": "You must first update your branch to the latest version." }) - changed = base_doc.share(form.cleaned_data['message']) + anwser, info = base_doc.would_share() - # update shared version if needed - if changed: - doc_new = doc.latest() - else: - doc_new = doc + if not anwser: + return response.SuccessAllOk().django_response({ + "result": "no-op", "message": info + }) - # the user wersion is the same - user_doc_new = base_doc + # check for unresolved conflicts + if base_doc.has_conflict_marks(): + return response.BadRequest().django_response({ + "reason": "unresolved-conflicts", + "message": "There are unresolved conflicts in your file. Fix them, and try again." + }) - # The client can compare parent_revision to revision - # to see if he needs to update user's view - # Same goes for shared view - - return response.SuccessAllOk().django_response({ - "result": "success", - "name": user_doc_new.id, - "user": user_doc_new.owner, + if not request.user.has_perm('api.share_document'): + # User is not permitted to make a merge, right away + # So we instead create a pull request in the database + try: + prq, created = PullRequest.objects.get_or_create( + comitter = request.user, + document = docid, + status = "N", + defaults = { + 'source_revision': str(base_doc.revision), + 'comment': form.cleaned_data['message'] or '$AUTO$ Document shared.', + } + ) + + # there can't be 2 pending request from same user + # for the same document + if not created: + prq.source_revision = str(base_doc.revision) + prq.comment = prq.comment + 'u\n\n' + (form.cleaned_data['message'] or u'') + prq.save() + + return response.RequestAccepted().django_response(\ + ticket_status=prq.status, \ + ticket_uri=reverse("pullrequest_view", args=[prq.id]) ) + except IntegrityError: + return response.EntityConflict().django_response({ + 'reason': 'request-already-exist' + }) + + changed = base_doc.share(form.cleaned_data['message']) + + # update shared version if needed + if changed: + doc_new = doc.latest() + else: + doc_new = doc + + # the user wersion is the same + user_doc_new = base_doc - "revision": user_doc_new.revision, - 'timestamp': user_doc_new.revision.timestamp, + # The client can compare parent_revision to revision + # to see if he needs to update user's view + # Same goes for shared view - "parent_revision": user_doc.revision, - "parent_timestamp": user_doc.revision.timestamp, + return response.SuccessAllOk().django_response({ + "result": "success", + "name": user_doc_new.id, + "user": user_doc_new.owner, - "shared_revision": doc_new.revision, - "shared_timestamp": doc_new.revision.timestamp, + "revision": user_doc_new.revision, + 'timestamp': user_doc_new.revision.timestamp, - "shared_parent_revision": doc.revision, - "shared_parent_timestamp": doc.revision.timestamp, - }) \ No newline at end of file + "parent_revision": user_doc.revision, + "parent_timestamp": user_doc.revision.timestamp, + + "shared_revision": doc_new.revision, + "shared_timestamp": doc_new.revision.timestamp, + + "shared_parent_revision": doc.revision, + "shared_parent_timestamp": doc.revision.timestamp, + }) + except wlrepo.OutdatedException, e: + return response.BadRequest().django_response({ + "reason": "not-fast-forward", + "message": e.message + }) + except wlrepo.LibraryException, e: + return response.InternalError().django_response({ + "reason": "merge-error", + "message": e.message + }) diff --git a/apps/api/handlers/text_handler.py b/apps/api/handlers/text_handler.py index 5f27a2ab..ba8bf717 100755 --- a/apps/api/handlers/text_handler.py +++ b/apps/api/handlers/text_handler.py @@ -64,8 +64,7 @@ class DocumentTextHandler(BaseHandler): if not chunk: return document.data('xml') - xdoc = parser.WLDocument.from_string(document.data('xml'),\ - parse_dublincore=False) + xdoc = parser.WLDocument.from_string(document.data('xml'), parse_dublincore=False) xchunk = xdoc.chunk(chunk) @@ -123,7 +122,7 @@ class DocumentTextHandler(BaseHandler): log.info(data[:600]) log.info(chunks) - xdoc = parser.WLDocument.from_string(data) + xdoc = parser.WLDocument.from_string(data, parse_dublincore=False) errors = xdoc.merge_chunks(chunks) if len(errors): diff --git a/lib/wlrepo/__init__.py b/lib/wlrepo/__init__.py index fc309dcd..ed0998cf 100755 --- a/lib/wlrepo/__init__.py +++ b/lib/wlrepo/__init__.py @@ -114,6 +114,9 @@ class LibraryException(Exception): class UpdateException(LibraryException): pass +class OutdatedException(LibraryException): + pass + class RevisionNotFound(LibraryException): def __init__(self, rev): LibraryException.__init__(self, "Revision %r not found." % rev) diff --git a/lib/wlrepo/mercurial_backend/document.py b/lib/wlrepo/mercurial_backend/document.py index 9a2c2aa2..77b8ead7 100755 --- a/lib/wlrepo/mercurial_backend/document.py +++ b/lib/wlrepo/mercurial_backend/document.py @@ -190,18 +190,22 @@ class MercurialDocument(wlrepo.Document): # | * # | | # We want to prevent stuff like this. - if self.parent().parentof(shared): + if self.parent().parentof(shared) and shared.parentof(self): return False, "Preventing zig-zag" - return True, "OK" - + return True, "All ok" def share(self, message): lock = self.library.lock() try: - result, info = self.would_share() + # check if the document is in "updated" state + if not self.up_to_date(): + raise wlrepo.OutdatedException("You must update your document before share.") - if not result: + # now check if there is anything to do + need_work, info = self.would_share() + + if not need_work: return self.shared() # The good situation @@ -215,15 +219,14 @@ class MercurialDocument(wlrepo.Document): # | | shared = self.shared() - if shared.ancestorof(self): + try: success = shared._revision.merge_with(self._revision, user=self.owner, message=message) - if not success: raise wlrepo.LibraryException("Merge failed.") return shared.latest() - - raise wlrepo.LibraryException("Unrecognized share-state.") + except Abort, e: + raise wlrepo.LibraryException( repr(e) ) finally: lock.release() -- 2.20.1