def test_emit_commit(self):
        b = Blob()
        b.data = b"FOO"
        t = Tree()
        t.add(b"foo", stat.S_IFREG | 0o644, b.id)
        c = Commit()
        c.committer = c.author = b"Jelmer <jelmer@host>"
        c.author_time = c.commit_time = 1271345553
        c.author_timezone = c.commit_timezone = 0
        c.message = b"msg"
        c.tree = t.id
        self.store.add_objects([(b, None), (t, None), (c, None)])
        self.fastexporter.emit_commit(c, b"refs/heads/master")
        self.assertEqual(
            b"""blob
mark :1
data 3
FOO
commit refs/heads/master
mark :2
author Jelmer <jelmer@host> 1271345553 +0000
committer Jelmer <jelmer@host> 1271345553 +0000
data 3
msg
M 644 :1 foo
""", self.stream.getvalue())
 def test_add(self):
     myhexsha = b'd80c186a03f423a81b39df39dc87fd269736ca86'
     x = Tree()
     x.add(b'myname', 0o100755, myhexsha)
     self.assertEqual(x[b'myname'], (0o100755, myhexsha))
     self.assertEqual(b'100755 myname\0' + hex_to_sha(myhexsha),
                      x.as_raw_string())
 def test_simple(self):
     myhexsha = b'd80c186a03f423a81b39df39dc87fd269736ca86'
     x = Tree()
     x[b'myname'] = (0o100755, myhexsha)
     self.assertEqual(b'100755 myname\0' + hex_to_sha(myhexsha),
                      x.as_raw_string())
     self.assertEqual(b'100755 myname\0' + hex_to_sha(myhexsha), bytes(x))
 def test_full_tree(self):
     c = self.make_commit(commit_time=30)
     t = Tree()
     t.add(b'data-x', 0o644, Blob().id)
     c.tree = t
     c1 = Commit()
     c1.set_raw_string(c.as_raw_string())
     self.assertEqual(t.id, c1.tree)
     self.assertEqual(c.as_raw_string(), c1.as_raw_string())
 def _get_example_tar_stream(self, *tar_stream_args, **tar_stream_kwargs):
     store = MemoryObjectStore()
     b1 = Blob.from_string(b"somedata")
     store.add_object(b1)
     t1 = Tree()
     t1.add(b"somename", 0o100644, b1.id)
     store.add_object(t1)
     stream = b''.join(
         tar_stream(store, t1, *tar_stream_args, **tar_stream_kwargs))
     return BytesIO(stream)
 def test_add_old_order(self):
     myhexsha = b'd80c186a03f423a81b39df39dc87fd269736ca86'
     x = Tree()
     warnings.simplefilter("ignore", DeprecationWarning)
     try:
         x.add(0o100755, b'myname', myhexsha)
     finally:
         warnings.resetwarnings()
     self.assertEqual(x[b'myname'], (0o100755, myhexsha))
     self.assertEqual(b'100755 myname\0' + hex_to_sha(myhexsha),
                      x.as_raw_string())
Beispiel #7
0
 def build_tree(path):
     tree = Tree()
     for basename, entry in trees[path].items():
         if isinstance(entry, dict):
             mode = stat.S_IFDIR
             sha = build_tree(pathjoin(path, basename))
         else:
             (mode, sha) = entry
         tree.add(basename, mode, sha)
     object_store.add_object(tree)
     return tree.id
Beispiel #8
0
def create_commit(marker=None):
    blob = Blob.from_string(b'The blob content ' + marker)
    tree = Tree()
    tree.add(b"thefile " + marker, 0o100644, blob.id)
    cmt = Commit()
    cmt.tree = tree.id
    cmt.author = cmt.committer = b"John Doe <*****@*****.**>"
    cmt.message = marker
    tz = parse_timezone(b'-0200')[0]
    cmt.commit_time = cmt.author_time = int(time.time())
    cmt.commit_timezone = cmt.author_timezone = tz
    return cmt, tree, blob
    def test_tree_copy_after_update(self):
        """Check Tree.id is correctly updated when the tree is copied after updated.
        """
        shas = []
        tree = Tree()
        shas.append(tree.id)
        tree.add(b'data', 0o644, Blob().id)
        copied = tree.copy()
        shas.append(tree.id)
        shas.append(copied.id)

        self.assertNotIn(shas[0], shas[1:])
        self.assertEqual(shas[1], shas[2])
    def test_tree_serialize(self):
        blob = make_object(Blob, data=b'i am a blob')
        tree = Tree()
        tree[b'blob'] = (stat.S_IFREG, blob.id)

        with self.assert_serialization_on_change(tree):
            tree[b'blob2'] = (stat.S_IFREG, blob.id)
    def test_git_dir(self):
        repo_dir = tempfile.mkdtemp()
        self.addCleanup(shutil.rmtree, repo_dir)
        with Repo.init(repo_dir) as repo:

            # Populate repo
            filea = Blob.from_string(b'file a')
            filee = Blob.from_string(b'd')

            tree = Tree()
            tree[b'.git/a'] = (stat.S_IFREG | 0o644, filea.id)
            tree[b'c/e'] = (stat.S_IFREG | 0o644, filee.id)

            repo.object_store.add_objects([(o, None)
                                           for o in [filea, filee, tree]])

            build_index_from_tree(repo.path, repo.index_path(),
                                  repo.object_store, tree.id)

            # Verify index entries
            index = repo.open_index()
            self.assertEqual(len(index), 1)

            # filea
            apath = os.path.join(repo.path, '.git', 'a')
            self.assertFalse(os.path.exists(apath))

            # filee
            epath = os.path.join(repo.path, 'c', 'e')
            self.assertTrue(os.path.exists(epath))
            self.assertReasonableIndexEntry(index[b'c/e'],
                                            stat.S_IFREG | 0o644, 1, filee.id)
            self.assertFileContents(epath, b'd')
    def test_symlink(self):
        repo_dir = tempfile.mkdtemp()
        self.addCleanup(shutil.rmtree, repo_dir)
        with Repo.init(repo_dir) as repo:

            # Populate repo
            filed = Blob.from_string(b'file d')
            filee = Blob.from_string(b'd')

            tree = Tree()
            tree[b'c/d'] = (stat.S_IFREG | 0o644, filed.id)
            tree[b'c/e'] = (stat.S_IFLNK, filee.id)  # symlink

            repo.object_store.add_objects([(o, None)
                                           for o in [filed, filee, tree]])

            build_index_from_tree(repo.path, repo.index_path(),
                                  repo.object_store, tree.id)

            # Verify index entries
            index = repo.open_index()

            # symlink to d
            epath = os.path.join(repo.path, 'c', 'e')
            self.assertTrue(os.path.exists(epath))
            self.assertReasonableIndexEntry(
                index[b'c/e'], stat.S_IFLNK,
                0 if sys.platform == 'win32' else 1, filee.id)
            self.assertFileContents(epath, 'd', symlink=True)
    def test_nonempty(self):
        repo_dir = tempfile.mkdtemp()
        self.addCleanup(shutil.rmtree, repo_dir)
        with Repo.init(repo_dir) as repo:

            # Populate repo
            filea = Blob.from_string(b'file a')
            fileb = Blob.from_string(b'file b')
            filed = Blob.from_string(b'file d')

            tree = Tree()
            tree[b'a'] = (stat.S_IFREG | 0o644, filea.id)
            tree[b'b'] = (stat.S_IFREG | 0o644, fileb.id)
            tree[b'c/d'] = (stat.S_IFREG | 0o644, filed.id)

            repo.object_store.add_objects([
                (o, None) for o in [filea, fileb, filed, tree]
            ])

            build_index_from_tree(repo.path, repo.index_path(),
                                  repo.object_store, tree.id)

            # Verify index entries
            index = repo.open_index()
            self.assertEqual(len(index), 3)

            # filea
            apath = os.path.join(repo.path, 'a')
            self.assertTrue(os.path.exists(apath))
            self.assertReasonableIndexEntry(index[b'a'], stat.S_IFREG | 0o644,
                                            6, filea.id)
            self.assertFileContents(apath, b'file a')

            # fileb
            bpath = os.path.join(repo.path, 'b')
            self.assertTrue(os.path.exists(bpath))
            self.assertReasonableIndexEntry(index[b'b'], stat.S_IFREG | 0o644,
                                            6, fileb.id)
            self.assertFileContents(bpath, b'file b')

            # filed
            dpath = os.path.join(repo.path, 'c', 'd')
            self.assertTrue(os.path.exists(dpath))
            self.assertReasonableIndexEntry(index[b'c/d'],
                                            stat.S_IFREG | 0o644, 6, filed.id)
            self.assertFileContents(dpath, b'file d')

            # Verify no extra files
            self.assertEqual(['.git', 'a', 'b', 'c'],
                             sorted(os.listdir(repo.path)))
            self.assertEqual(['d'],
                             sorted(os.listdir(os.path.join(repo.path, 'c'))))
    def test_git_submodule_exists(self):
        repo_dir = tempfile.mkdtemp()
        self.addCleanup(shutil.rmtree, repo_dir)
        with Repo.init(repo_dir) as repo:
            filea = Blob.from_string(b'file alalala')

            subtree = Tree()
            subtree[b'a'] = (stat.S_IFREG | 0o644, filea.id)

            c = Commit()
            c.tree = subtree.id
            c.committer = c.author = b'Somebody <*****@*****.**>'
            c.commit_time = c.author_time = 42342
            c.commit_timezone = c.author_timezone = 0
            c.parents = []
            c.message = b'Subcommit'

            tree = Tree()
            tree[b'c'] = (S_IFGITLINK, c.id)

            os.mkdir(os.path.join(repo_dir, 'c'))
            repo.object_store.add_objects([(o, None) for o in [tree]])

            build_index_from_tree(repo.path, repo.index_path(),
                                  repo.object_store, tree.id)

            # Verify index entries
            index = repo.open_index()
            self.assertEqual(len(index), 1)

            # filea
            apath = os.path.join(repo.path, 'c/a')
            self.assertFalse(os.path.exists(apath))

            # dir c
            cpath = os.path.join(repo.path, 'c')
            self.assertTrue(os.path.isdir(cpath))
            self.assertEqual(index[b'c'][4], S_IFGITLINK)  # mode
            self.assertEqual(index[b'c'][8], c.id)  # sha
    def test_empty(self):
        repo_dir = tempfile.mkdtemp()
        self.addCleanup(shutil.rmtree, repo_dir)
        with Repo.init(repo_dir) as repo:
            tree = Tree()
            repo.object_store.add_object(tree)

            build_index_from_tree(repo.path, repo.index_path(),
                                  repo.object_store, tree.id)

            # Verify index entries
            index = repo.open_index()
            self.assertEqual(len(index), 0)

            # Verify no files
            self.assertEqual(['.git'], os.listdir(repo.path))
    def _do_test_parse_tree(self, parse_tree):
        dir = os.path.join(os.path.dirname(__file__), 'data', 'trees')
        o = Tree.from_path(hex_to_filename(dir, tree_sha))
        self.assertEqual([(b'a', 0o100644, a_sha), (b'b', 0o100644, b_sha)],
                         list(parse_tree(o.as_raw_string())))
        # test a broken tree that has a leading 0 on the file mode
        broken_tree = b'0100644 foo\0' + hex_to_sha(a_sha)

        def eval_parse_tree(*args, **kwargs):
            return list(parse_tree(*args, **kwargs))

        self.assertEqual([(b'foo', 0o100644, a_sha)],
                         eval_parse_tree(broken_tree))
        self.assertRaises(ObjectFormatException,
                          eval_parse_tree,
                          broken_tree,
                          strict=True)
def commit_tree_changes(object_store, tree, changes):
    """Commit a specified set of changes to a tree structure.

    This will apply a set of changes on top of an existing tree, storing new
    objects in object_store.

    changes are a list of tuples with (path, mode, object_sha).
    Paths can be both blobs and trees. See the mode and
    object sha to None deletes the path.

    This method works especially well if there are only a small
    number of changes to a big tree. For a large number of changes
    to a large tree, use e.g. commit_tree.

    :param object_store: Object store to store new objects in
        and retrieve old ones from.
    :param tree: Original tree root
    :param changes: changes to apply
    :return: New tree root object
    """
    # TODO(jelmer): Save up the objects and add them using .add_objects
    # rather than with individual calls to .add_object.
    nested_changes = {}
    for (path, new_mode, new_sha) in changes:
        try:
            (dirname, subpath) = path.split(b'/', 1)
        except ValueError:
            if new_sha is None:
                del tree[path]
            else:
                tree[path] = (new_mode, new_sha)
        else:
            nested_changes.setdefault(dirname, []).append(
                (subpath, new_mode, new_sha))
    for name, subchanges in nested_changes.items():
        try:
            orig_subtree = object_store[tree[name][1]]
        except KeyError:
            orig_subtree = Tree()
        subtree = commit_tree_changes(object_store, orig_subtree, subchanges)
        if len(subtree) == 0:
            del tree[name]
        else:
            tree[name] = (stat.S_IFDIR, subtree.id)
    object_store.add_object(tree)
    return tree
Beispiel #18
0
 def test_tree_diff_submodule(self):
     f = BytesIO()
     store = MemoryObjectStore()
     tree1 = Tree()
     tree1.add(b"asubmodule", S_IFGITLINK,
               b"06d0bdd9e2e20377b3180e4986b14c8549b393e4")
     tree2 = Tree()
     tree2.add(b"asubmodule", S_IFGITLINK,
               b"cc975646af69f279396d4d5e1379ac6af80ee637")
     store.add_objects([(o, None) for o in [tree1, tree2]])
     write_tree_diff(f, store, tree1.id, tree2.id)
     self.assertEqual([
         b'diff --git a/asubmodule b/asubmodule',
         b'index 06d0bdd..cc97564 160000',
         b'--- a/asubmodule',
         b'+++ b/asubmodule',
         b'@@ -1 +1 @@',
         b'-Submodule commit 06d0bdd9e2e20377b3180e4986b14c8549b393e4',
         b'+Submodule commit cc975646af69f279396d4d5e1379ac6af80ee637',
     ],
                      f.getvalue().splitlines())
Beispiel #19
0
    def test_send_pack_new_ref(self):
        self.rin.write(
            b'0064310ca9477129b8586fa2afc779c1f57cf64bba6c '
            b'refs/heads/master\x00 report-status delete-refs ofs-delta\n'
            b'0000000eunpack ok\n'
            b'0019ok refs/heads/blah12\n'
            b'0000')
        self.rin.seek(0)

        tree = Tree()
        commit = Commit()
        commit.tree = tree
        commit.parents = []
        commit.author = commit.committer = b'test user'
        commit.commit_time = commit.author_time = 1174773719
        commit.commit_timezone = commit.author_timezone = 0
        commit.encoding = b'UTF-8'
        commit.message = b'test message'

        def determine_wants(refs):
            return {
                b'refs/heads/blah12': commit.id,
                b'refs/heads/master':
                b'310ca9477129b8586fa2afc779c1f57cf64bba6c'
            }

        def generate_pack_data(have, want, ofs_delta=False):
            return pack_objects_to_data([
                (commit, None),
                (tree, b''),
            ])

        f = BytesIO()
        write_pack_data(f, *generate_pack_data(None, None))
        self.client.send_pack(b'/', determine_wants, generate_pack_data)
        self.assertIn(self.rout.getvalue(), [
            b'007f0000000000000000000000000000000000000000 ' + commit.id +
            b' refs/heads/blah12\x00report-status ofs-delta0000' +
            f.getvalue(), b'007f0000000000000000000000000000000000000000 ' +
            commit.id + b' refs/heads/blah12\x00ofs-delta report-status0000' +
            f.getvalue()
        ])
    def setUp(self):
        super(GraftsInMemoryRepoTests, self).setUp()
        r = self._repo = MemoryRepo()

        self._shas = []

        tree = Tree()

        commit_kwargs = {
            'committer': b'Test Committer <*****@*****.**>',
            'author': b'Test Author <*****@*****.**>',
            'commit_timestamp': 12395,
            'commit_timezone': 0,
            'author_timestamp': 12395,
            'author_timezone': 0,
            'tree': tree.id
        }

        self._shas.append(r.do_commit(b'empty commit', **commit_kwargs))
        self._shas.append(r.do_commit(b'empty commit', **commit_kwargs))
        self._shas.append(r.do_commit(b'empty commit', **commit_kwargs))
Beispiel #21
0
    def test_send_pack_no_sideband64k_with_update_ref_error(self):
        # No side-bank-64k reported by server shouldn't try to parse
        # side band data
        pkts = [
            b'55dcc6bf963f922e1ed5c4bbaaefcfacef57b1d7 capabilities^{}'
            b'\x00 report-status delete-refs ofs-delta\n', b'', b"unpack ok",
            b"ng refs/foo/bar pre-receive hook declined", b''
        ]
        for pkt in pkts:
            if pkt == b'':
                self.rin.write(b"0000")
            else:
                self.rin.write(("%04x" % (len(pkt) + 4)).encode('ascii') + pkt)
        self.rin.seek(0)

        tree = Tree()
        commit = Commit()
        commit.tree = tree
        commit.parents = []
        commit.author = commit.committer = b'test user'
        commit.commit_time = commit.author_time = 1174773719
        commit.commit_timezone = commit.author_timezone = 0
        commit.encoding = b'UTF-8'
        commit.message = b'test message'

        def determine_wants(refs):
            return {
                b'refs/foo/bar': commit.id,
            }

        def generate_pack_data(have, want, ofs_delta=False):
            return pack_objects_to_data([
                (commit, None),
                (tree, ''),
            ])

        self.assertRaises(UpdateRefsError, self.client.send_pack, "blah",
                          determine_wants, generate_pack_data)
Beispiel #22
0
 def test_simple_bytesio(self):
     f = BytesIO()
     c = Commit()
     c.committer = c.author = b"Jelmer <*****@*****.**>"
     c.commit_time = c.author_time = 1271350201
     c.commit_timezone = c.author_timezone = 0
     c.message = b"This is the first line\nAnd this is the second line.\n"
     c.tree = Tree().id
     write_commit_patch(f, c, b"CONTENTS", (1, 1), version="custom")
     f.seek(0)
     lines = f.readlines()
     self.assertTrue(lines[0].startswith(
         b"From 0b0d34d1b5b596c928adc9a727a4b9e03d025298"))
     self.assertEqual(lines[1], b"From: Jelmer <*****@*****.**>\n")
     self.assertTrue(lines[2].startswith(b"Date: "))
     self.assertEqual([
         b"Subject: [PATCH 1/1] This is the first line\n",
         b"And this is the second line.\n", b"\n", b"\n", b"---\n"
     ], lines[3:8])
     self.assertEqual([b"CONTENTS-- \n", b"custom\n"], lines[-2:])
     if len(lines) >= 12:
         # diffstat may not be present
         self.assertEqual(lines[8], b" 0 files changed\n")
    def test_norewrite(self):
        repo_dir = tempfile.mkdtemp()
        self.addCleanup(shutil.rmtree, repo_dir)
        with Repo.init(repo_dir) as repo:
            # Populate repo
            filea = Blob.from_string(b'file a')
            filea_path = os.path.join(repo_dir, 'a')
            tree = Tree()
            tree[b'a'] = (stat.S_IFREG | 0o644, filea.id)

            repo.object_store.add_objects([(o, None) for o in [filea, tree]])

            # First Write
            build_index_from_tree(repo.path, repo.index_path(),
                                  repo.object_store, tree.id)
            # Use sync as metadata can be cached on some FS
            os.sync()
            mtime = os.stat(filea_path).st_mtime

            # Test Rewrite
            build_index_from_tree(repo.path, repo.index_path(),
                                  repo.object_store, tree.id)
            os.sync()
            self.assertEqual(mtime, os.stat(filea_path).st_mtime)

            # Modify content
            with open(filea_path, 'wb') as fh:
                fh.write(b'test a')
            os.sync()
            mtime = os.stat(filea_path).st_mtime

            # Test rewrite
            build_index_from_tree(repo.path, repo.index_path(),
                                  repo.object_store, tree.id)
            os.sync()
            with open(filea_path, 'rb') as fh:
                self.assertEqual(b'file a', fh.read())
    def test_no_decode_encode(self):
        repo_dir = tempfile.mkdtemp()
        repo_dir_bytes = repo_dir.encode(sys.getfilesystemencoding())
        self.addCleanup(shutil.rmtree, repo_dir)
        with Repo.init(repo_dir) as repo:

            # Populate repo
            file = Blob.from_string(b'foo')

            tree = Tree()
            latin1_name = u'À'.encode('latin1')
            latin1_path = os.path.join(repo_dir_bytes, latin1_name)
            utf8_name = u'À'.encode('utf8')
            utf8_path = os.path.join(repo_dir_bytes, utf8_name)
            tree[latin1_name] = (stat.S_IFREG | 0o644, file.id)
            tree[utf8_name] = (stat.S_IFREG | 0o644, file.id)

            repo.object_store.add_objects([(o, None) for o in [file, tree]])

            try:
                os.path.exists(latin1_path)
            except UnicodeDecodeError:
                # This happens e.g. with python3.6 on Windows.
                # It implicitly decodes using utf8, which doesn't work.
                self.skipTest('can not implicitly convert as utf8')

            build_index_from_tree(repo.path, repo.index_path(),
                                  repo.object_store, tree.id)

            # Verify index entries
            index = repo.open_index()
            self.assertIn(latin1_name, index)
            self.assertIn(utf8_name, index)

            self.assertTrue(os.path.exists(latin1_path))

            self.assertTrue(os.path.exists(utf8_path))
Beispiel #25
0
 def test_tree_diff(self):
     f = BytesIO()
     store = MemoryObjectStore()
     added = Blob.from_string(b"add\n")
     removed = Blob.from_string(b"removed\n")
     changed1 = Blob.from_string(b"unchanged\nremoved\n")
     changed2 = Blob.from_string(b"unchanged\nadded\n")
     unchanged = Blob.from_string(b"unchanged\n")
     tree1 = Tree()
     tree1.add(b"removed.txt", 0o644, removed.id)
     tree1.add(b"changed.txt", 0o644, changed1.id)
     tree1.add(b"unchanged.txt", 0o644, changed1.id)
     tree2 = Tree()
     tree2.add(b"added.txt", 0o644, added.id)
     tree2.add(b"changed.txt", 0o644, changed2.id)
     tree2.add(b"unchanged.txt", 0o644, changed1.id)
     store.add_objects([
         (o, None) for o in
         [tree1, tree2, added, removed, changed1, changed2, unchanged]
     ])
     write_tree_diff(f, store, tree1.id, tree2.id)
     self.assertEqual([
         b'diff --git /dev/null b/added.txt',
         b'new mode 644',
         b'index 0000000..76d4bb8 644',
         b'--- /dev/null',
         b'+++ b/added.txt',
         b'@@ -0,0 +1 @@',
         b'+add',
         b'diff --git a/changed.txt b/changed.txt',
         b'index bf84e48..1be2436 644',
         b'--- a/changed.txt',
         b'+++ b/changed.txt',
         b'@@ -1,2 +1,2 @@',
         b' unchanged',
         b'-removed',
         b'+added',
         b'diff --git a/removed.txt /dev/null',
         b'deleted mode 644',
         b'index 2c3f0b3..0000000',
         b'--- a/removed.txt',
         b'+++ /dev/null',
         b'@@ -1 +0,0 @@',
         b'-removed',
     ],
                      f.getvalue().splitlines())
 def assertMergeFails(self, merge_entries, name, mode, sha):
     t = Tree()
     t[name] = (mode, sha)
     self.assertRaises((TypeError, ValueError), merge_entries, '', t, t)
 def test_tree_copy(self):
     blob = make_object(Blob, data=b'i am a blob')
     tree = Tree()
     tree[b'blob'] = (stat.S_IFREG, blob.id)
     self.assert_copy(tree)
 def test_iter(self):
     t = Tree()
     t[b'foo'] = (0o100644, a_sha)
     self.assertEqual(set([b'foo']), set(t))
 def test_tree_update_id(self):
     x = Tree()
     x[b'a.c'] = (0o100755, b'd80c186a03f423a81b39df39dc87fd269736ca86')
     self.assertEqual(b'0c5c6bc2c081accfbc250331b19e43b904ab9cdd', x.id)
     x[b'a.b'] = (stat.S_IFDIR, b'd80c186a03f423a81b39df39dc87fd269736ca86')
     self.assertEqual(b'07bfcb5f3ada15bbebdfa3bbb8fd858a363925c8', x.id)
 def test_tree_items_dir_sort(self):
     x = Tree()
     for name, item in _TREE_ITEMS.items():
         x[name] = item
     self.assertEqual(_SORTED_TREE_ITEMS, x.items())