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
Exemple #3
0
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')
Exemple #4
0
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'))
Exemple #5
0
# 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)