def test_unresolved_merge(self): # setup the server repository server_repo = self.make_repo('server') page_path = 'wiki_root/wikitext/FrontPage' texts = ('This the default front page.\n', 'This fork 1 of the front page.\n', 'This fork 2 of the front page.\n',) print "---" print "Main : FrontPage" print "fork 1: ", ("%s_%s" % (page_path, new_sha(texts[1]). hexdigest())) print "fork 2: ", ("%s_%s" % (page_path, new_sha(texts[2]). hexdigest())) print "---" self.commit_revision(server_repo, ((page_path, texts[0]), ("%s_%s" % (page_path, new_sha(texts[1]). hexdigest()), texts[1]), ("%s_%s" % (page_path, new_sha(texts[2]). hexdigest()), texts[2]), ), 'Initial checkin of server repo.') # pull the client repo client_repo = self.clone_repo(server_repo, 'client', '0') # get a write overlay for the client repo overlay = self.get_write_overlay(client_repo) page_bytes = 'Modify front page without deleting forks.\n' # write an updated file into it. overlay.write(os.path.join(client_repo.root, page_path), page_bytes) # verify write. self.assertTrue(overlay.read(os.path.join(client_repo.root, page_path)) == page_bytes) # make a submission bundle w/ 2 unresolved forks try: raw_zip_bytes = self.make_submission_zip(client_repo) self.assertTrue(False) except SubmitError, err0: print "Got expected error:" print err0 self.assertTrue(err0.illegal)
def has_forked_version(self, overlay, page_path, raw_bytes): if not overlay.exists(page_path): return False sha_value = new_sha(raw_bytes).hexdigest() versioned_path = "%s_%s" % (page_path, sha_value) if not overlay.exists(versioned_path): return False if new_sha(overlay.read(versioned_path)).hexdigest() != sha_value: print "SHA FAILS: ", versioned_path self.assertTrue(False) # quick and dirty test for has forks self.assertTrue(has_forks(overlay)) return True
def unicode_apply_patch(old_text, patch, updated_sha, name): """ Helper wrapper around apply_patch() which takes a unicode string for old_text. raises a SubmitError if the SHA1 of the patched text != updated_sha. """ ret = apply_patch(old_text.encode('utf8'), patch) if new_sha(ret).digest() != updated_sha: raise SubmitError("Patch failed to validate: %s" % name, True) return ret.decode('utf8')
def utf8_sha(unicode_text): """ Return a SHA1 hash instance for the utf8 8-bit string rep of unicode_text.""" return new_sha(unicode_text.encode('utf8'))
# Reasons submission were rejected. REJECT_UNKNOWN = 0 # Dunno why submission failed. REJECT_FCPFAIL = 1 # FCP request for CHK failed REJECT_NOTRUST = 2 # Not enough trust REJECT_APPLIED = 3 # Submission was already fully applied. # Hmmm no longer needed? REJECT_PARTIAL = 4 # Submission was already partially applied. REJECT_CONFLICT = 5 # Submission couldn't be applied because of conflict. REJECT_ILLEGAL = 6 # Submission bundle malformed or illegal. SENTINEL_VER = '000000000000' MAX_INFO_LEN = 1024 # Arbitrary, reasonable bound. #----------------------------------------------------------# CRLF = '\x0d\x0a' EMPTY_FILE_SHA_HEX = new_sha('').hexdigest() EMPTY_FILE_SHA = new_sha('').digest() #----------------------------------------------------------# # diff / patch helper funcs # # LATER: Use unified diffs? # RESEARCH: No patch in python standard modules? # 0) http://docs.python.org/library/difflib.html # can write diffs (context, unified) but doesn't # read them. # restore() operates on the entire file rep. ie. not just deltas # Double check. # 1) http://code.google.com/p/python-patch/ # Looks promising, but too new to rely on. # 2) http://code.google.com/p/google-diff-match-patch/ # Looks like it would do the trick but forces licensing
class ConflictTests(RepoTests): ############################################################ # Smoketest create, remove, modify with conflict def has_forked_version(self, overlay, page_path, raw_bytes): if not overlay.exists(page_path): return False sha_value = new_sha(raw_bytes).hexdigest() versioned_path = "%s_%s" % (page_path, sha_value) if not overlay.exists(versioned_path): return False if new_sha(overlay.read(versioned_path)).hexdigest() != sha_value: print "SHA FAILS: ", versioned_path self.assertTrue(False) # quick and dirty test for has forks self.assertTrue(has_forks(overlay)) return True def test_create_file_conflict(self): # setup the server repository server_repo = self.make_repo('server') original_page_bytes = 'Server side addition of a new page.\n' self.commit_revision(server_repo, (('wiki_root/wikitext/FrontPage', 'This the default front page.\n'),), 'Initial checkin of server repo.') self.commit_revision(server_repo, (('wiki_root/wikitext/NewPage', original_page_bytes),), 'Second checkin of server repo.') # pull the client repo but only up to the first version client_repo = self.clone_repo(server_repo, 'client', '0') # get a write overlay for the client repo overlay = self.get_write_overlay(client_repo) page_path = 'wiki_root/wikitext/NewPage' client_page_path = os.path.join(client_repo.root, page_path) page_bytes = 'Conflicting client side changes.\n\n' self.assertTrue(not overlay.exists(client_page_path)) # write a new file into it. overlay.write(client_page_path, page_bytes) # make a submission bundle self.assertTrue(overlay.exists(client_page_path)) raw_zip_bytes = self.make_submission_zip(client_repo) #(fms_id, usk_hash, base_version, chk, length) msg_id = 'fake_msg_id_000' submission_tuple = (DEFAULT_SUBMITTER, '000000000000', hex_version(server_repo, '0')[:12], 'CHK@fakechk', len(raw_zip_bytes)) server_overlay = self.get_hg_overlay(server_repo) server_overlay.version = hex_version(server_repo, '0') # clients version server_page_path = os.path.join(server_repo.root, page_path) self.assertTrue(not server_overlay.exists(server_page_path)) # apply the submission bundle to the server repo self.get_applier(server_repo).apply_submission(msg_id, submission_tuple, raw_zip_bytes, os.path.join( self.tmp_dir, '_tmp__applying')) self.assertTrue(not server_overlay.exists(server_page_path)) server_overlay.version = hex_version(server_repo) # new tip self.assertTrue(server_overlay.exists(server_page_path)) # Check that the head version is the servers. self.assertTrue(server_overlay.read(server_page_path) == original_page_bytes) # Check that the forked version was created. self.has_forked_version(server_overlay, server_page_path, page_bytes) def test_remove_file_conflict(self): # setup the server repository server_repo = self.make_repo('server') self.commit_revision(server_repo, (('wiki_root/wikitext/FrontPage', 'This the default front page.\n'),), 'Initial checkin of server repo.') self.commit_revision(server_repo, (('wiki_root/wikitext/FrontPage', 'This the updated front page.\n'),), 'Second checkin of server repo.') # pull the client repo client_repo = self.clone_repo(server_repo, 'client', '0') # get a write overlay for the client repo overlay = self.get_write_overlay(client_repo) page_path = 'wiki_root/wikitext/FrontPage' page_bytes = '' # write a new file into it. overlay.write(os.path.join(client_repo.root, page_path), page_bytes) # make a submission bundle raw_zip_bytes = self.make_submission_zip(client_repo) #(fms_id, usk_hash, base_version, chk, length) msg_id = 'fake_msg_id_000' submission_tuple = (DEFAULT_SUBMITTER, '000000000000', hex_version(server_repo)[:12], 'CHK@fakechk', len(raw_zip_bytes)) server_overlay = self.get_hg_overlay(server_repo) server_overlay.version = hex_version(server_repo, '0') server_page_path = os.path.join(server_repo.root, page_path) # Check that the target page exists. self.assertTrue(server_overlay.exists(server_page_path)) # apply the submission bundle to the server repo self.get_applier(server_repo).apply_submission(msg_id, submission_tuple, raw_zip_bytes, os.path.join( self.tmp_dir, '_tmp__applying')) self.assertTrue(server_overlay.exists(server_page_path)) server_overlay.version = hex_version(server_repo) # new tip self.assertTrue(server_overlay.exists(server_page_path)) # Check that the head version is the servers. self.assertTrue(server_overlay.read(server_page_path) == 'This the updated front page.\n') # Check that the forked version was created. self.has_forked_version(server_overlay, server_page_path, '') def test_modify_file_conflict(self): # setup the server repository server_repo = self.make_repo('server') original_page_bytes = 'This the default front page.\n' self.commit_revision(server_repo, (('wiki_root/wikitext/FrontPage', original_page_bytes),), 'Initial checkin of server repo.') self.commit_revision(server_repo, (('wiki_root/wikitext/FrontPage', 'Updated front page.\n'),), 'Initial checkin of server repo.') # pull the client repo client_repo = self.clone_repo(server_repo, 'client', '0') # get a write overlay for the client repo overlay = self.get_write_overlay(client_repo) page_path = 'wiki_root/wikitext/FrontPage' page_bytes = original_page_bytes + 'Client changes.\n' # write the updated file into it. overlay.write(os.path.join(client_repo.root, page_path), page_bytes) # make a submission bundle raw_zip_bytes = self.make_submission_zip(client_repo) #(fms_id, usk_hash, base_version, chk, length) msg_id = 'fake_msg_id_000' submission_tuple = (DEFAULT_SUBMITTER, '000000000000', hex_version(server_repo)[:12], 'CHK@fakechk', len(raw_zip_bytes)) server_overlay = self.get_hg_overlay(server_repo) server_overlay.version = hex_version(server_repo, '0') server_page_path = os.path.join(server_repo.root, page_path) self.assertTrue(server_overlay.exists(server_page_path)) self.assertTrue(server_overlay.read(server_page_path) == original_page_bytes) # apply the submission bundle to the server repo self.get_applier(server_repo).apply_submission(msg_id, submission_tuple, raw_zip_bytes, os.path.join( self.tmp_dir, '_tmp__applying')) self.assertTrue(server_overlay.exists(server_page_path)) self.assertTrue(server_overlay.read(server_page_path) == original_page_bytes) server_overlay.version = hex_version(server_repo) # new tip self.assertTrue(server_overlay.exists(server_page_path)) # Check that the head versions i unchanged. self.assertTrue(server_overlay.read(server_page_path) == 'Updated front page.\n') # Check that the forked version was created. self.has_forked_version(server_overlay, server_page_path, original_page_bytes + 'Client changes.\n') def test_unresolved_merge(self): # setup the server repository server_repo = self.make_repo('server') page_path = 'wiki_root/wikitext/FrontPage' texts = ('This the default front page.\n', 'This fork 1 of the front page.\n', 'This fork 2 of the front page.\n',) print "---" print "Main : FrontPage" print "fork 1: ", ("%s_%s" % (page_path, new_sha(texts[1]). hexdigest())) print "fork 2: ", ("%s_%s" % (page_path, new_sha(texts[2]). hexdigest())) print "---" self.commit_revision(server_repo, ((page_path, texts[0]), ("%s_%s" % (page_path, new_sha(texts[1]). hexdigest()), texts[1]), ("%s_%s" % (page_path, new_sha(texts[2]). hexdigest()), texts[2]), ), 'Initial checkin of server repo.') # pull the client repo client_repo = self.clone_repo(server_repo, 'client', '0') # get a write overlay for the client repo overlay = self.get_write_overlay(client_repo) page_bytes = 'Modify front page without deleting forks.\n' # write an updated file into it. overlay.write(os.path.join(client_repo.root, page_path), page_bytes) # verify write. self.assertTrue(overlay.read(os.path.join(client_repo.root, page_path)) == page_bytes) # make a submission bundle w/ 2 unresolved forks try: raw_zip_bytes = self.make_submission_zip(client_repo) self.assertTrue(False) except SubmitError, err0: print "Got expected error:" print err0 self.assertTrue(err0.illegal) # Resolve one fork in client overlay. overlay.write(os.path.join(client_repo.root, "%s_%s" % (page_path, new_sha(texts[1]). hexdigest())), '') # make a submission bundle w/ 1 unresolved fork try: raw_zip_bytes = self.make_submission_zip(client_repo) self.assertTrue(False) except SubmitError, err1: print "Got second expected error:" print err1 self.assertTrue(err1.illegal)
hexdigest())), '') # make a submission bundle w/ 1 unresolved fork try: raw_zip_bytes = self.make_submission_zip(client_repo) self.assertTrue(False) except SubmitError, err1: print "Got second expected error:" print err1 self.assertTrue(err1.illegal) # Resolve the final fork in client overlay. overlay.write(os.path.join(client_repo.root, "%s_%s" % (page_path, new_sha(texts[2]). hexdigest())), '') # make a submission bundle w/ all forks resolved. raw_zip_bytes = self.make_submission_zip(client_repo) #(fms_id, usk_hash, base_version, chk, length) msg_id = 'fake_msg_id_000' submission_tuple = (DEFAULT_SUBMITTER, '000000000000', hex_version(server_repo)[:12], 'CHK@fakechk', len(raw_zip_bytes)) server_overlay = self.get_hg_overlay(server_repo)