def test_tree_changes(self): blob_a1 = make_object(Blob, data=b"a1") blob_a2 = make_object(Blob, data=b"a2") blob_b = make_object(Blob, data=b"b") for blob in [blob_a1, blob_a2, blob_b]: self.store.add_object(blob) blobs_1 = [(b"a", blob_a1.id, 0o100644), (b"b", blob_b.id, 0o100644)] tree1_id = commit_tree(self.store, blobs_1) blobs_2 = [(b"a", blob_a2.id, 0o100644), (b"b", blob_b.id, 0o100644)] tree2_id = commit_tree(self.store, blobs_2) change_a = ( (b"a", b"a"), (0o100644, 0o100644), (blob_a1.id, blob_a2.id), ) self.assertEqual([change_a], list(self.store.tree_changes(tree1_id, tree2_id))) self.assertEqual( [ change_a, ((b"b", b"b"), (0o100644, 0o100644), (blob_b.id, blob_b.id)), ], list( self.store.tree_changes(tree1_id, tree2_id, want_unchanged=True)), )
def commit_handler(self, cmd): """Process a CommitCommand.""" commit = Commit() if cmd.author is not None: author = cmd.author else: author = cmd.committer (author_name, author_email, author_timestamp, author_timezone) = author (committer_name, committer_email, commit_timestamp, commit_timezone) = cmd.committer commit.author = author_name + b" <" + author_email + b">" commit.author_timezone = author_timezone commit.author_time = int(author_timestamp) commit.committer = committer_name + b" <" + committer_email + b">" commit.commit_timezone = commit_timezone commit.commit_time = int(commit_timestamp) commit.message = cmd.message commit.parents = [] if cmd.from_: self._reset_base(cmd.from_) for filecmd in cmd.iter_files(): if filecmd.name == b"filemodify": if filecmd.data is not None: blob = Blob.from_string(filecmd.data) self.repo.object_store.add(blob) blob_id = blob.id else: assert filecmd.dataref.startswith(b":"), \ ("non-marker refs not supported yet (%r)" % filecmd.dataref) blob_id = self.markers[filecmd.dataref[1:]] self._contents[filecmd.path] = (filecmd.mode, blob_id) elif filecmd.name == b"filedelete": del self._contents[filecmd.path] elif filecmd.name == b"filecopy": self._contents[filecmd.dest_path] = self._contents[ filecmd.src_path] elif filecmd.name == b"filerename": self._contents[filecmd.new_path] = self._contents[ filecmd.old_path] del self._contents[filecmd.old_path] elif filecmd.name == b"filedeleteall": self._contents = {} else: raise Exception("Command %s not supported" % filecmd.name) commit.tree = commit_tree( self.repo.object_store, ((path, hexsha, mode) for (path, (mode, hexsha)) in self._contents.items())) if self.last_commit != ZERO_SHA: commit.parents.append(self.last_commit) for merge in cmd.merges: if merge.startswith(b':'): merge = self.markers[merge[1:]] commit.parents.append(merge) self.repo.object_store.add_object(commit) self.repo[cmd.ref] = commit.id self.last_commit = commit.id if cmd.mark: self.markers[cmd.mark] = commit.id
def test_iter_tree_contents_include_trees(self): blob_a = make_object(Blob, data='a') blob_b = make_object(Blob, data='b') blob_c = make_object(Blob, data='c') for blob in [blob_a, blob_b, blob_c]: self.store.add_object(blob) blobs = [ ('a', blob_a.id, 0100644), ('ad/b', blob_b.id, 0100644), ('ad/bd/c', blob_c.id, 0100755), ] tree_id = commit_tree(self.store, blobs) tree = self.store[tree_id] tree_ad = self.store[tree['ad'][1]] tree_bd = self.store[tree_ad['bd'][1]] expected = [ TreeEntry('', 0040000, tree_id), TreeEntry('a', 0100644, blob_a.id), TreeEntry('ad', 0040000, tree_ad.id), TreeEntry('ad/b', 0100644, blob_b.id), TreeEntry('ad/bd', 0040000, tree_bd.id), TreeEntry('ad/bd/c', 0100755, blob_c.id), ] actual = self.store.iter_tree_contents(tree_id, include_trees=True) self.assertEquals(expected, list(actual))
def commit_handler(self, cmd): """Process a CommitCommand.""" commit = Commit() if cmd.author is not None: author = cmd.author else: author = cmd.committer (author_name, author_email, author_timestamp, author_timezone) = author (committer_name, committer_email, commit_timestamp, commit_timezone) = cmd.committer commit.author = "%s <%s>" % (author_name, author_email) commit.author_timezone = author_timezone commit.author_time = int(author_timestamp) commit.committer = "%s <%s>" % (committer_name, committer_email) commit.commit_timezone = commit_timezone commit.commit_time = int(commit_timestamp) commit.message = cmd.message commit.parents = [] contents = {} commit.tree = commit_tree( self.repo.object_store, ((path, hexsha, mode) for (path, (mode, hexsha)) in contents.iteritems()) ) if self.last_commit is not None: commit.parents.append(self.last_commit) commit.parents += cmd.merges self.repo.object_store.add_object(commit) self.repo[cmd.ref] = commit.id self.last_commit = commit.id if cmd.mark: self.markers[cmd.mark] = commit.id
def test_iter_tree_contents_include_trees(self): blob_a = make_object(Blob, data=b'a') blob_b = make_object(Blob, data=b'b') blob_c = make_object(Blob, data=b'c') for blob in [blob_a, blob_b, blob_c]: self.store.add_object(blob) blobs = [ (b'a', blob_a.id, 0o100644), (b'ad/b', blob_b.id, 0o100644), (b'ad/bd/c', blob_c.id, 0o100755), ] tree_id = commit_tree(self.store, blobs) tree = self.store[tree_id] tree_ad = self.store[tree[b'ad'][1]] tree_bd = self.store[tree_ad[b'bd'][1]] expected = [ TreeEntry(b'', 0o040000, tree_id), TreeEntry(b'a', 0o100644, blob_a.id), TreeEntry(b'ad', 0o040000, tree_ad.id), TreeEntry(b'ad/b', 0o100644, blob_b.id), TreeEntry(b'ad/bd', 0o040000, tree_bd.id), TreeEntry(b'ad/bd/c', 0o100755, blob_c.id), ] actual = self.store.iter_tree_contents(tree_id, include_trees=True) self.assertEqual(expected, list(actual))
def disable_ff_and_make_dummy_commit(self): # disable non-fast-forward pushes to the server dest = repo.Repo(os.path.join(self.gitroot, 'dest')) run_git_or_fail(['config', 'receive.denyNonFastForwards', 'true'], cwd=dest.path) b = objects.Blob.from_string('hi') dest.object_store.add_object(b) t = index.commit_tree(dest.object_store, [('hi', b.id, 0100644)])
def test_tree_changes(self): blob_a1 = make_object(Blob, data='a1') blob_a2 = make_object(Blob, data='a2') blob_b = make_object(Blob, data='b') for blob in [blob_a1, blob_a2, blob_b]: self.store.add_object(blob) blobs_1 = [('a', blob_a1.id, 0100644), ('b', blob_b.id, 0100644)] tree1_id = commit_tree(self.store, blobs_1) blobs_2 = [('a', blob_a2.id, 0100644), ('b', blob_b.id, 0100644)] tree2_id = commit_tree(self.store, blobs_2) change_a = (('a', 'a'), (0100644, 0100644), (blob_a1.id, blob_a2.id)) self.assertEquals([change_a], list(self.store.tree_changes(tree1_id, tree2_id))) self.assertEquals( [change_a, (('b', 'b'), (0100644, 0100644), (blob_b.id, blob_b.id))], list(self.store.tree_changes(tree1_id, tree2_id, want_unchanged=True)))
def test_single_blob(self): blob = Blob() blob.data = b"foo" self.store.add_object(blob) blobs = [(b"bla", blob.id, stat.S_IFREG)] rootid = commit_tree(self.store, blobs) self.assertEqual(rootid, b"1a1e80437220f9312e855c37ac4398b68e5c1d50") self.assertEqual((stat.S_IFREG, blob.id), self.store[rootid][b"bla"]) self.assertEqual(set([rootid, blob.id]), set(self.store._data.keys()))
def commit_handler(self, cmd): """Process a CommitCommand.""" commit = Commit() if cmd.author is not None: author = cmd.author else: author = cmd.committer (author_name, author_email, author_timestamp, author_timezone) = author (committer_name, committer_email, commit_timestamp, commit_timezone) = cmd.committer commit.author = author_name + b" <" + author_email + b">" commit.author_timezone = author_timezone commit.author_time = int(author_timestamp) commit.committer = committer_name + b" <" + committer_email + b">" commit.commit_timezone = commit_timezone commit.commit_time = int(commit_timestamp) commit.message = cmd.message commit.parents = [] if cmd.from_: cmd.from_ = self.lookup_object(cmd.from_) self._reset_base(cmd.from_) for filecmd in cmd.iter_files(): if filecmd.name == b"filemodify": if filecmd.data is not None: blob = Blob.from_string(filecmd.data) self.repo.object_store.add(blob) blob_id = blob.id else: blob_id = self.lookup_object(filecmd.dataref) self._contents[filecmd.path] = (filecmd.mode, blob_id) elif filecmd.name == b"filedelete": del self._contents[filecmd.path] elif filecmd.name == b"filecopy": self._contents[filecmd.dest_path] = self._contents[ filecmd.src_path] elif filecmd.name == b"filerename": self._contents[filecmd.new_path] = self._contents[ filecmd.old_path] del self._contents[filecmd.old_path] elif filecmd.name == b"filedeleteall": self._contents = {} else: raise Exception("Command %s not supported" % filecmd.name) commit.tree = commit_tree( self.repo.object_store, ((path, hexsha, mode) for (path, (mode, hexsha)) in self._contents.items())) if self.last_commit != ZERO_SHA: commit.parents.append(self.last_commit) for merge in cmd.merges: commit.parents.append(self.lookup_object(merge)) self.repo.object_store.add_object(commit) self.repo[cmd.ref] = commit.id self.last_commit = commit.id if cmd.mark: self.markers[cmd.mark] = commit.id
def export_hg_commit(self, rev): self.ui.note(_("converting revision %s\n") % hex(rev)) oldenc = self.swap_out_encoding() ctx = self.repo.changectx(rev) extra = ctx.extra() commit = Commit() (time, timezone) = ctx.date() commit.author = self.get_git_author(ctx) commit.author_time = int(time) commit.author_timezone = -timezone if 'committer' in extra: # fixup timezone (name, timestamp, timezone) = extra['committer'].rsplit(' ', 2) commit.committer = name commit.commit_time = timestamp # work around a timezone format change if int(timezone) % 60 != 0: #pragma: no cover timezone = parse_timezone(timezone) # Newer versions of Dulwich return a tuple here if isinstance(timezone, tuple): timezone, neg_utc = timezone commit._commit_timezone_neg_utc = neg_utc else: timezone = -int(timezone) commit.commit_timezone = timezone else: commit.committer = commit.author commit.commit_time = commit.author_time commit.commit_timezone = commit.author_timezone commit.parents = [] for parent in self.get_git_parents(ctx): hgsha = hex(parent.node()) git_sha = self.map_git_get(hgsha) if git_sha: commit.parents.append(git_sha) commit.message = self.get_git_message(ctx) if 'encoding' in extra: commit.encoding = extra['encoding'] tree_sha = commit_tree(self.git.object_store, self.iterblobs(ctx)) commit.tree = tree_sha self.git.object_store.add_object(commit) self.map_set(commit.id, ctx.hex()) self.swap_out_encoding(oldenc) return commit.id
def make_dummy_commit(self, dest): b = objects.Blob.from_string(b'hi') dest.object_store.add_object(b) t = index.commit_tree(dest.object_store, [(b'hi', b.id, 0o100644)]) c = objects.Commit() c.author = c.committer = b'Foo Bar <*****@*****.**>' c.author_time = c.commit_time = 0 c.author_timezone = c.commit_timezone = 0 c.message = b'hi' c.tree = t dest.object_store.add_object(c) return c.id
def test_tree_changes(self): blob_a1 = make_object(Blob, data='a1') blob_a2 = make_object(Blob, data='a2') blob_b = make_object(Blob, data='b') for blob in [blob_a1, blob_a2, blob_b]: self.store.add_object(blob) blobs_1 = [('a', blob_a1.id, 0100644), ('b', blob_b.id, 0100644)] tree1_id = commit_tree(self.store, blobs_1) blobs_2 = [('a', blob_a2.id, 0100644), ('b', blob_b.id, 0100644)] tree2_id = commit_tree(self.store, blobs_2) change_a = (('a', 'a'), (0100644, 0100644), (blob_a1.id, blob_a2.id)) self.assertEqual([change_a], list(self.store.tree_changes(tree1_id, tree2_id))) self.assertEqual([ change_a, (('b', 'b'), (0100644, 0100644), (blob_b.id, blob_b.id)) ], list( self.store.tree_changes(tree1_id, tree2_id, want_unchanged=True)))
def test_nested(self): blob = Blob() blob.data = "foo" self.store.add_object(blob) blobs = [("bla/bar", blob.id, stat.S_IFREG)] rootid = commit_tree(self.store, blobs) self.assertEqual(rootid, "d92b959b216ad0d044671981196781b3258fa537") dirid = self.store[rootid]["bla"][1] self.assertEqual(dirid, "c1a1deb9788150829579a8b4efa6311e7b638650") self.assertEqual((stat.S_IFDIR, dirid), self.store[rootid]["bla"]) self.assertEqual((stat.S_IFREG, blob.id), self.store[dirid]["bar"]) self.assertEqual(set([rootid, dirid, blob.id]), set(self.store._data.keys()))
def push(self, committer=None, author=None, message=None): """Create a new stash. Args: committer: Optional committer name to use author: Optional author name to use message: Optional commit message """ # First, create the index commit. commit_kwargs = {} if committer is not None: commit_kwargs["committer"] = committer if author is not None: commit_kwargs["author"] = author index = self._repo.open_index() index_tree_id = index.commit(self._repo.object_store) index_commit_id = self._repo.do_commit( ref=None, tree=index_tree_id, message=b"Index stash", merge_heads=[self._repo.head()], no_verify=True, **commit_kwargs ) # Then, the working tree one. stash_tree_id = commit_tree( self._repo.object_store, iter_fresh_objects( index, os.fsencode(self._repo.path), object_store=self._repo.object_store, ), ) if message is None: message = b"A stash on " + self._repo.head() # TODO(jelmer): Just pass parents into do_commit()? self._repo.refs[self._ref] = self._repo.head() cid = self._repo.do_commit( ref=self._ref, tree=stash_tree_id, message=message, merge_heads=[index_commit_id], no_verify=True, **commit_kwargs ) return cid
def test_nested(self): blob = Blob() blob.data = b"foo" self.store.add_object(blob) blobs = [(b"bla/bar", blob.id, stat.S_IFREG)] rootid = commit_tree(self.store, blobs) self.assertEqual(rootid, b"d92b959b216ad0d044671981196781b3258fa537") dirid = self.store[rootid][b"bla"][1] self.assertEqual(dirid, b"c1a1deb9788150829579a8b4efa6311e7b638650") self.assertEqual((stat.S_IFDIR, dirid), self.store[rootid][b"bla"]) self.assertEqual((stat.S_IFREG, blob.id), self.store[dirid][b"bar"]) self.assertEqual(set([rootid, dirid, blob.id]), set(self.store._data.keys()))
def commit(self, message): self._validate_unicode_text(message, 'commit message') c = Commit() c.parents = [ self.repository.lookup_bzr_revision_id(revid)[0] for revid in self.parents ] c.tree = commit_tree(self.store, self._iterblobs()) encoding = self._revprops.pop(u'git-explicit-encoding', 'utf-8') c.encoding = encoding.encode('ascii') c.committer = fix_person_identifier(self._committer.encode(encoding)) try: author = self._revprops.pop('author') except KeyError: try: authors = self._revprops.pop('authors').splitlines() except KeyError: author = self._committer else: if len(authors) > 1: raise Exception("Unable to convert multiple authors") elif len(authors) == 0: author = self._committer else: author = authors[0] c.author = fix_person_identifier(author.encode(encoding)) bugstext = self._revprops.pop('bugs', None) if bugstext is not None: message += "\n" for url, status in bugtracker.decode_bug_urls(bugstext): if status == bugtracker.FIXED: message += "Fixes: %s\n" % url elif status == bugtracker.RELATED: message += "Bug: %s\n" % url else: raise bugtracker.InvalidBugStatus(status) if self._revprops: raise NotImplementedError(self._revprops) c.commit_time = int(self._timestamp) c.author_time = int(self._timestamp) c.commit_timezone = self._timezone c.author_timezone = self._timezone c.message = message.encode(encoding) if (self._config_stack.get('create_signatures') == _mod_config.SIGN_ALWAYS): strategy = gpg.GPGStrategy(self._config_stack) c.gpgsig = strategy.sign(c.as_raw_string(), gpg.MODE_DETACH) self.store.add_object(c) self.repository.commit_write_group() self._new_revision_id = self._mapping.revision_id_foreign_to_bzr(c.id) return self._new_revision_id
def commit_tree(self, entries): commit_blobs = [] for entry in entries: if len(entry) == 2: path, obj = entry mode = F else: path, obj, mode = entry if isinstance(obj, Blob): self.store.add_object(obj) sha = obj.id else: sha = obj commit_blobs.append((path, sha, mode)) return self.store[commit_tree(self.store, commit_blobs)]
def test_iter_tree_contents(self): blob_a = make_object(Blob, data='a') blob_b = make_object(Blob, data='b') blob_c = make_object(Blob, data='c') for blob in [blob_a, blob_b, blob_c]: self.store.add_object(blob) blobs = [ ('a', blob_a.id, 0100644), ('ad/b', blob_b.id, 0100644), ('ad/bd/c', blob_c.id, 0100755), ('ad/c', blob_c.id, 0100644), ('c', blob_c.id, 0100644), ] tree_id = commit_tree(self.store, blobs) self.assertEquals([TreeEntry(p, m, h) for (p, h, m) in blobs], list(self.store.iter_tree_contents(tree_id)))
def setUp(self): super(CommitTreeChangesTests, self).setUp() self.store = MemoryObjectStore() self.blob_a = make_object(Blob, data=b'a') self.blob_b = make_object(Blob, data=b'b') self.blob_c = make_object(Blob, data=b'c') for blob in [self.blob_a, self.blob_b, self.blob_c]: self.store.add_object(blob) blobs = [ (b'a', self.blob_a.id, 0o100644), (b'ad/b', self.blob_b.id, 0o100644), (b'ad/bd/c', self.blob_c.id, 0o100755), (b'ad/c', self.blob_c.id, 0o100644), (b'c', self.blob_c.id, 0o100644), ] self.tree_id = commit_tree(self.store, blobs)
def setUp(self): super(CommitTreeChangesTests, self).setUp() self.store = MemoryObjectStore() self.blob_a = make_object(Blob, data=b"a") self.blob_b = make_object(Blob, data=b"b") self.blob_c = make_object(Blob, data=b"c") for blob in [self.blob_a, self.blob_b, self.blob_c]: self.store.add_object(blob) blobs = [ (b"a", self.blob_a.id, 0o100644), (b"ad/b", self.blob_b.id, 0o100644), (b"ad/bd/c", self.blob_c.id, 0o100755), (b"ad/c", self.blob_c.id, 0o100644), (b"c", self.blob_c.id, 0o100644), ] self.tree_id = commit_tree(self.store, blobs)
def setUp(self): TestCase.setUp(self) self.store = MemoryObjectStore() blob_a = make_object(Blob, data=b'a') blob_b = make_object(Blob, data=b'b') blob_c = make_object(Blob, data=b'c') for blob in [blob_a, blob_b, blob_c]: self.store.add_object(blob) blobs = [ (b'a', blob_a.id, 0o100644), (b'ad/b', blob_b.id, 0o100644), (b'ad/bd/c', blob_c.id, 0o100755), (b'ad/c', blob_c.id, 0o100644), (b'c', blob_c.id, 0o100644), ] self.tree_id = commit_tree(self.store, blobs)
def test_iter_tree_contents(self): blob_a = make_object(Blob, data=b'a') blob_b = make_object(Blob, data=b'b') blob_c = make_object(Blob, data=b'c') for blob in [blob_a, blob_b, blob_c]: self.store.add_object(blob) blobs = [ (b'a', blob_a.id, 0o100644), (b'ad/b', blob_b.id, 0o100644), (b'ad/bd/c', blob_c.id, 0o100755), (b'ad/c', blob_c.id, 0o100644), (b'c', blob_c.id, 0o100644), ] tree_id = commit_tree(self.store, blobs) self.assertEqual([TreeEntry(p, m, h) for (p, h, m) in blobs], list(self.store.iter_tree_contents(tree_id)))
def setUp(self): TestCase.setUp(self) self.store = MemoryObjectStore() blob_a = make_object(Blob, data='a') blob_b = make_object(Blob, data='b') blob_c = make_object(Blob, data='c') for blob in [blob_a, blob_b, blob_c]: self.store.add_object(blob) blobs = [ ('a', blob_a.id, 0100644), ('ad/b', blob_b.id, 0100644), ('ad/bd/c', blob_c.id, 0100755), ('ad/c', blob_c.id, 0100644), ('c', blob_c.id, 0100644), ] self.tree_id = commit_tree(self.store, blobs)
def setUp(self): TestCase.setUp(self) self.store = MemoryObjectStore() blob_a = make_object(Blob, data=b"a") blob_b = make_object(Blob, data=b"b") blob_c = make_object(Blob, data=b"c") for blob in [blob_a, blob_b, blob_c]: self.store.add_object(blob) blobs = [ (b"a", blob_a.id, 0o100644), (b"ad/b", blob_b.id, 0o100644), (b"ad/bd/c", blob_c.id, 0o100755), (b"ad/c", blob_c.id, 0o100644), (b"c", blob_c.id, 0o100644), (b"d", blob_c.id, S_IFGITLINK), ] self.tree_id = commit_tree(self.store, blobs)
def push(self, committer=None, author=None, message=None): """Create a new stash. :param committer: Optional committer name to use :param author: Optional author name to use :param message: Optional commit message """ # First, create the index commit. commit_kwargs = {} if committer is not None: commit_kwargs['committer'] = committer if author is not None: commit_kwargs['author'] = author index = self._repo.open_index() index_tree_id = index.commit(self._repo.object_store) index_commit_id = self._repo.do_commit( ref=None, tree=index_tree_id, message=b"Index stash", merge_heads=[self._repo.head()], **commit_kwargs) # Then, the working tree one. stash_tree_id = commit_tree( self._repo.object_store, iter_fresh_objects( index, self._repo.path, object_store=self._repo.object_store)) if message is None: message = b"A stash on " + self._repo.head() # TODO(jelmer): Just pass parents into do_commit()? self._repo.refs[self._ref] = self._repo.head() cid = self._repo.do_commit( ref=self._ref, tree=stash_tree_id, message=message, merge_heads=[index_commit_id], **commit_kwargs) return cid
def __setitem__(self, path, raw): # XXX: I don't have much idea, what I'm doing here and I might # just corrupt your repository... # Mark directory as special (None, None) marker value if raw is None: super(Head, self).__setitem__(path, (None, None)) return # Get old mode or use the default try: mode = super(Head, self).__getitem__(path)[1] except KeyError: mode = 0100644 # Get existing entries for the content tree entries = [(key, sha_mode[0], cleanup_mode(sha_mode[1])) for key, sha_mode in super(Head, self).iteritems() if sha_mode[0] is not None and key is not path] # Get author # TODO: refactor to use plone.api or maybe use product_config from Products.CMFCore.utils import getToolByName portal_members = getToolByName(getSite(), 'portal_membership') member = portal_members.getAuthenticatedMember() author = '{0:s} <{1:s}>'.format( member.getProperty('fullname', '') or member.getId(), member.getProperty('email', '') or '*****@*****.**') # Get timezone tz_diff = dateutil.tz.tzlocal().utcoffset(datetime.datetime.now()) # Create commit commit = Commit() commit.author = author commit.committer = commit.author commit.commit_time = int(time.time()) commit.author_time = commit.commit_time commit.commit_timezone = tz_diff.seconds commit.author_timezone = tz_diff.seconds if tz_diff < datetime.timedelta(0): commit._author_timezone_neg_utc = True commit._commit_timezone_neg_utc = True commit.encoding = 'UTF-8' commit.message = 'Update {0:s}'.format(path) commit.parents = [self._head] # Create blob and commit tree blob = Blob.from_string(raw) entries.append((path, blob.id, cleanup_mode(mode))) commit.tree = commit_tree(self._repo.object_store, entries) # Save blob and commit self._repo.object_store.add_object(blob) self._repo.object_store.add_object(commit) def determine_wants(haves): # Set new head for the branch return {self.__name__: commit.id} # Push to remote refs = self.__parent__._client.send_pack( self.__parent__._host_path, determine_wants, self._repo.object_store.generate_pack_contents, progress=logger.info) # Update heads for ref, sha in refs.items(): if sha in self._repo.object_store: self._repo.refs[ref] = sha # Update "index" super(Head, self).__setitem__(path, (blob.id, mode))
def build_commit_graph(object_store, commit_spec, trees=None, attrs=None): """Build a commit graph from a concise specification. Sample usage: >>> c1, c2, c3 = build_commit_graph(store, [[1], [2, 1], [3, 1, 2]]) >>> store[store[c3].parents[0]] == c1 True >>> store[store[c3].parents[1]] == c2 True If not otherwise specified, commits will refer to the empty tree and have commit times increasing in the same order as the commit spec. Args: object_store: An ObjectStore to commit objects to. commit_spec: An iterable of iterables of ints defining the commit graph. Each entry defines one commit, and entries must be in topological order. The first element of each entry is a commit number, and the remaining elements are its parents. The commit numbers are only meaningful for the call to make_commits; since real commit objects are created, they will get created with real, opaque SHAs. trees: An optional dict of commit number -> tree spec for building trees for commits. The tree spec is an iterable of (path, blob, mode) or (path, blob) entries; if mode is omitted, it defaults to the normal file mode (0100644). attrs: A dict of commit number -> (dict of attribute -> value) for assigning additional values to the commits. Returns: The list of commit objects created. Raises: ValueError: If an undefined commit identifier is listed as a parent. """ if trees is None: trees = {} if attrs is None: attrs = {} commit_time = 0 nums = {} commits = [] for commit in commit_spec: commit_num = commit[0] try: parent_ids = [nums[pn] for pn in commit[1:]] except KeyError as e: (missing_parent, ) = e.args raise ValueError("Unknown parent %i" % missing_parent) blobs = [] for entry in trees.get(commit_num, []): if len(entry) == 2: path, blob = entry entry = (path, blob, F) path, blob, mode = entry blobs.append((path, blob.id, mode)) object_store.add_object(blob) tree_id = commit_tree(object_store, blobs) commit_attrs = { "message": ("Commit %i" % commit_num).encode("ascii"), "parents": parent_ids, "tree": tree_id, "commit_time": commit_time, } commit_attrs.update(attrs.get(commit_num, {})) commit_obj = make_commit(**commit_attrs) # By default, increment the time by a lot. Out-of-order commits should # be closer together than this because their main cause is clock skew. commit_time = commit_attrs["commit_time"] + 100 nums[commit_num] = commit_obj.id object_store.add_object(commit_obj) commits.append(commit_obj) return commits
def __setitem__(self, path, raw): # XXX: I don't have much idea, what I'm doing here and I might # just corrupt your repository... # Mark directory as special (None, None) marker value if raw is None: super(Head, self).__setitem__(path, (None, None)) return # Get old mode or use the default try: mode = super(Head, self).__getitem__(path)[1] except KeyError: mode = 0100644 # Get existing entries for the content tree entries = [(key, sha_mode[0], cleanup_mode(sha_mode[1])) for key, sha_mode in super(Head, self).iteritems() if sha_mode[0] is not None and key is not path] # Get author # TODO: refactor to use plone.api or maybe use product_config from Products.CMFCore.utils import getToolByName portal_members = getToolByName(getSite(), 'portal_membership') member = portal_members.getAuthenticatedMember() author = '{0:s} <{1:s}>'.format( member.getProperty('fullname', '') or member.getId(), member.getProperty('email', '') or '*****@*****.**' ) # Get timezone tz_diff = dateutil.tz.tzlocal().utcoffset(datetime.datetime.now()) # Create commit commit = Commit() commit.author = author commit.committer = commit.author commit.commit_time = int(time.time()) commit.author_time = commit.commit_time commit.commit_timezone = tz_diff.seconds commit.author_timezone = tz_diff.seconds if tz_diff < datetime.timedelta(0): commit._author_timezone_neg_utc = True commit._commit_timezone_neg_utc = True commit.encoding = 'UTF-8' commit.message = 'Update {0:s}'.format(path) commit.parents = [self._head] # Create blob and commit tree blob = Blob.from_string(raw) entries.append((path, blob.id, cleanup_mode(mode))) commit.tree = commit_tree(self._repo.object_store, entries) # Save blob and commit self._repo.object_store.add_object(blob) self._repo.object_store.add_object(commit) def determine_wants(haves): # Set new head for the branch return {self.__name__: commit.id} # Push to remote refs = self.__parent__._client.send_pack( self.__parent__._host_path, determine_wants, self._repo.object_store.generate_pack_contents, progress=logger.info ) # Update heads for ref, sha in refs.items(): if sha in self._repo.object_store: self._repo.refs[ref] = sha # Update "index" super(Head, self).__setitem__(path, (blob.id, mode))
def make_dummy_commit(self, dest): b = objects.Blob.from_string('hi') dest.object_store.add_object(b) t = index.commit_tree(dest.object_store, [('hi', b.id, 0100644)])
def build_commit_graph(object_store, commit_spec, trees=None, attrs=None): """Build a commit graph from a concise specification. Sample usage: >>> c1, c2, c3 = build_commit_graph(store, [[1], [2, 1], [3, 1, 2]]) >>> store[store[c3].parents[0]] == c1 True >>> store[store[c3].parents[1]] == c2 True If not otherwise specified, commits will refer to the empty tree and have commit times increasing in the same order as the commit spec. :param object_store: An ObjectStore to commit objects to. :param commit_spec: An iterable of iterables of ints defining the commit graph. Each entry defines one commit, and entries must be in topological order. The first element of each entry is a commit number, and the remaining elements are its parents. The commit numbers are only meaningful for the call to make_commits; since real commit objects are created, they will get created with real, opaque SHAs. :param trees: An optional dict of commit number -> tree spec for building trees for commits. The tree spec is an iterable of (path, blob, mode) or (path, blob) entries; if mode is omitted, it defaults to the normal file mode (0100644). :param attrs: A dict of commit number -> (dict of attribute -> value) for assigning additional values to the commits. :return: The list of commit objects created. :raise ValueError: If an undefined commit identifier is listed as a parent. """ if trees is None: trees = {} if attrs is None: attrs = {} commit_time = 0 nums = {} commits = [] for commit in commit_spec: commit_num = commit[0] try: parent_ids = [nums[pn] for pn in commit[1:]] except KeyError as e: missing_parent, = e.args raise ValueError('Unknown parent %i' % missing_parent) blobs = [] for entry in trees.get(commit_num, []): if len(entry) == 2: path, blob = entry entry = (path, blob, F) path, blob, mode = entry blobs.append((path, blob.id, mode)) object_store.add_object(blob) tree_id = commit_tree(object_store, blobs) commit_attrs = { 'message': 'Commit %i' % commit_num, 'parents': parent_ids, 'tree': tree_id, 'commit_time': commit_time, } commit_attrs.update(attrs.get(commit_num, {})) commit_obj = make_commit(**commit_attrs) # By default, increment the time by a lot. Out-of-order commits should # be closer together than this because their main cause is clock skew. commit_time = commit_attrs['commit_time'] + 100 nums[commit_num] = commit_obj.id object_store.add_object(commit_obj) commits.append(commit_obj) return commits