1836
1932
self.pb.update(message, self.count, self.total)
1935
class CommitBuilder(object):
1936
"""Provides an interface to build up a commit.
1938
This allows describing a tree to be committed without needing to
1939
know the internals of the format of the repository.
1941
def __init__(self, repository, parents, config, timestamp=None,
1942
timezone=None, committer=None, revprops=None,
1944
"""Initiate a CommitBuilder.
1946
:param repository: Repository to commit to.
1947
:param parents: Revision ids of the parents of the new revision.
1948
:param config: Configuration to use.
1949
:param timestamp: Optional timestamp recorded for commit.
1950
:param timezone: Optional timezone for timestamp.
1951
:param committer: Optional committer to set for commit.
1952
:param revprops: Optional dictionary of revision properties.
1953
:param revision_id: Optional revision id.
1955
self._config = config
1957
if committer is None:
1958
self._committer = self._config.username()
1960
assert isinstance(committer, basestring), type(committer)
1961
self._committer = committer
1963
self.new_inventory = Inventory()
1964
self._new_revision_id = revision_id
1965
self.parents = parents
1966
self.repository = repository
1969
if revprops is not None:
1970
self._revprops.update(revprops)
1972
if timestamp is None:
1973
self._timestamp = time.time()
1975
self._timestamp = long(timestamp)
1977
if timezone is None:
1978
self._timezone = local_time_offset()
1980
self._timezone = int(timezone)
1982
self._generate_revision_if_needed()
1984
def commit(self, message):
1985
"""Make the actual commit.
1987
:return: The revision id of the recorded revision.
1989
rev = Revision(timestamp=self._timestamp,
1990
timezone=self._timezone,
1991
committer=self._committer,
1993
inventory_sha1=self.inv_sha1,
1994
revision_id=self._new_revision_id,
1995
properties=self._revprops)
1996
rev.parent_ids = self.parents
1997
self.repository.add_revision(self._new_revision_id, rev,
1998
self.new_inventory, self._config)
1999
return self._new_revision_id
2001
def finish_inventory(self):
2002
"""Tell the builder that the inventory is finished."""
2003
self.new_inventory.revision_id = self._new_revision_id
2004
self.inv_sha1 = self.repository.add_inventory(
2005
self._new_revision_id,
2010
def _gen_revision_id(self):
2011
"""Return new revision-id."""
2012
s = '%s-%s-' % (self._config.user_email(),
2013
compact_date(self._timestamp))
2014
s += hexlify(rand_bytes(8))
2017
def _generate_revision_if_needed(self):
2018
"""Create a revision id if None was supplied.
2020
If the repository can not support user-specified revision ids
2021
they should override this function and raise UnsupportedOperation
2022
if _new_revision_id is not None.
2024
:raises: UnsupportedOperation
2026
if self._new_revision_id is None:
2027
self._new_revision_id = self._gen_revision_id()
2029
def record_entry_contents(self, ie, parent_invs, path, tree):
2030
"""Record the content of ie from tree into the commit if needed.
2032
:param ie: An inventory entry present in the commit.
2033
:param parent_invs: The inventories of the parent revisions of the
2035
:param path: The path the entry is at in the tree.
2036
:param tree: The tree which contains this entry and should be used to
2039
self.new_inventory.add(ie)
2041
# ie.revision is always None if the InventoryEntry is considered
2042
# for committing. ie.snapshot will record the correct revision
2043
# which may be the sole parent if it is untouched.
2044
if ie.revision is not None:
2046
previous_entries = ie.find_previous_heads(
2048
self.repository.weave_store,
2049
self.repository.get_transaction())
2050
# we are creating a new revision for ie in the history store
2052
ie.snapshot(self._new_revision_id, path, previous_entries, tree, self)
2054
def modified_directory(self, file_id, file_parents):
2055
"""Record the presence of a symbolic link.
2057
:param file_id: The file_id of the link to record.
2058
:param file_parents: The per-file parent revision ids.
2060
self._add_text_to_weave(file_id, [], file_parents.keys())
2062
def modified_file_text(self, file_id, file_parents,
2063
get_content_byte_lines, text_sha1=None,
2065
"""Record the text of file file_id
2067
:param file_id: The file_id of the file to record the text of.
2068
:param file_parents: The per-file parent revision ids.
2069
:param get_content_byte_lines: A callable which will return the byte
2071
:param text_sha1: Optional SHA1 of the file contents.
2072
:param text_size: Optional size of the file contents.
2074
mutter('storing text of file {%s} in revision {%s} into %r',
2075
file_id, self._new_revision_id, self.repository.weave_store)
2076
# special case to avoid diffing on renames or
2078
if (len(file_parents) == 1
2079
and text_sha1 == file_parents.values()[0].text_sha1
2080
and text_size == file_parents.values()[0].text_size):
2081
previous_ie = file_parents.values()[0]
2082
versionedfile = self.repository.weave_store.get_weave(file_id,
2083
self.repository.get_transaction())
2084
versionedfile.clone_text(self._new_revision_id,
2085
previous_ie.revision, file_parents.keys())
2086
return text_sha1, text_size
2088
new_lines = get_content_byte_lines()
2089
# TODO: Rather than invoking sha_strings here, _add_text_to_weave
2090
# should return the SHA1 and size
2091
self._add_text_to_weave(file_id, new_lines, file_parents.keys())
2092
return bzrlib.osutils.sha_strings(new_lines), \
2093
sum(map(len, new_lines))
2095
def modified_link(self, file_id, file_parents, link_target):
2096
"""Record the presence of a symbolic link.
2098
:param file_id: The file_id of the link to record.
2099
:param file_parents: The per-file parent revision ids.
2100
:param link_target: Target location of this link.
2102
self._add_text_to_weave(file_id, [], file_parents.keys())
2104
def _add_text_to_weave(self, file_id, new_lines, parents):
2105
versionedfile = self.repository.weave_store.get_weave_or_empty(
2106
file_id, self.repository.get_transaction())
2107
versionedfile.add_lines(self._new_revision_id, parents, new_lines)
2108
versionedfile.clear_cache()
1839
2111
# Copied from xml.sax.saxutils
1840
2112
def _unescape_xml(data):
1841
2113
"""Unescape &, <, and > in a string of data.