def append_entry(cls, config_reader, filepath, oldbinsha, newbinsha, message): """Append a new log entry to the revlog at filepath. :param config_reader: configuration reader of the repository - used to obtain user information. May be None :param filepath: full path to the log file :param oldbinsha: binary sha of the previous commit :param newbinsha: binary sha of the current commit :param message: message describing the change to the reference :param write: If True, the changes will be written right away. Otherwise the change will not be written :return: RefLogEntry objects which was appended to the log :note: As we are append-only, concurrent access is not a problem as we do not interfere with readers.""" if len(oldbinsha) != 20 or len(newbinsha) != 20: raise ValueError("Shas need to be given in binary format") #END handle sha type assure_directory_exists(filepath, is_file=True) entry = RefLogEntry((bin_to_hex(oldbinsha), bin_to_hex(newbinsha), Actor.committer(config_reader), (int(time.time()), time.altzone), message)) lf = LockFile(filepath) lf._obtain_lock_or_raise() fd = open(filepath, 'a') try: fd.write(repr(entry)) finally: fd.close() lf._release_lock() #END handle write operation return entry
def append_entry(cls, config_reader, filepath, oldbinsha, newbinsha, message): """Append a new log entry to the revlog at filepath. :param config_reader: configuration reader of the repository - used to obtain user information. May be None :param filepath: full path to the log file :param oldbinsha: binary sha of the previous commit :param newbinsha: binary sha of the current commit :param message: message describing the change to the reference :param write: If True, the changes will be written right away. Otherwise the change will not be written :return: RefLogEntry objects which was appended to the log :note: As we are append-only, concurrent access is not a problem as we do not interfere with readers.""" if len(oldbinsha) != 20 or len(newbinsha) != 20: raise ValueError("Shas need to be given in binary format") # END handle sha type assure_directory_exists(filepath, is_file=True) entry = RefLogEntry((bin_to_hex(oldbinsha), bin_to_hex(newbinsha), Actor.committer( config_reader), (int(time.time()), time.altzone), message)) lf = LockFile(filepath) lf._obtain_lock_or_raise() fd = open(filepath, 'a') try: fd.write(repr(entry)) finally: fd.close() lf._release_lock() # END handle write operation return entry
def to_file(self, filepath): """Write the contents of the reflog instance to a file at the given filepath. :param filepath: path to file, parent directories are assumed to exist""" lfd = LockedFD(filepath) assure_directory_exists(filepath, is_file=True) fp = lfd.open(write=True, stream=True) try: self._serialize(fp) lfd.commit() except Exception: # on failure it rolls back automatically, but we make it clear lfd.rollback() raise
def append_entry(cls, config_reader: Union[Actor, 'GitConfigParser', 'SectionConstraint', None], filepath: PathLike, oldbinsha: bytes, newbinsha: bytes, message: str, write: bool = True) -> 'RefLogEntry': """Append a new log entry to the revlog at filepath. :param config_reader: configuration reader of the repository - used to obtain user information. May also be an Actor instance identifying the committer directly or None. :param filepath: full path to the log file :param oldbinsha: binary sha of the previous commit :param newbinsha: binary sha of the current commit :param message: message describing the change to the reference :param write: If True, the changes will be written right away. Otherwise the change will not be written :return: RefLogEntry objects which was appended to the log :note: As we are append-only, concurrent access is not a problem as we do not interfere with readers.""" if len(oldbinsha) != 20 or len(newbinsha) != 20: raise ValueError("Shas need to be given in binary format") # END handle sha type assure_directory_exists(filepath, is_file=True) first_line = message.split('\n')[0] if isinstance(config_reader, Actor): committer = config_reader # mypy thinks this is Actor | Gitconfigparser, but why? else: committer = Actor.committer(config_reader) entry = RefLogEntry((bin_to_hex(oldbinsha).decode('ascii'), bin_to_hex(newbinsha).decode('ascii'), committer, (int(_time.time()), _time.altzone), first_line)) if write: lf = LockFile(filepath) lf._obtain_lock_or_raise() fd = open(filepath, 'ab') try: fd.write(entry.format().encode(defenc)) finally: fd.close() lf._release_lock() # END handle write operation return entry
def set_reference(self, ref, logmsg=None): """Set ourselves to the given ref. It will stay a symbol if the ref is a Reference. Otherwise an Object, given as Object instance or refspec, is assumed and if valid, will be set which effectively detaches the refererence if it was a purely symbolic one. :param ref: SymbolicReference instance, hexadecimal sha string or refspec string Only if the ref is a SymbolicRef instance, we will point to it. Everthiny else is dereferenced to obtain the actual object. :param logmsg: If set to a string, the message will be used in the reflog. Otherwise, a reflog entry is not written for the changed reference. The previous commit of the entry will be the commit we point to now. See also: log_append() :return: self :note: This symbolic reference will not be dereferenced. For that, see ``set_object(...)``""" write_value = None obj = None if isinstance(ref, SymbolicReference): write_value = "ref: %s" % ref.path elif isinstance(ref, self.ObjectCls): obj = ref write_value = ref.hexsha elif isinstance(ref, basestring): try: obj = self.repo.resolve_object(ref + "^{}") # optionally deref tags write_value = obj.hexsha except BadObject: raise ValueError("Could not extract object from %s" % ref) # END end try string else: raise ValueError("Unrecognized Value: %r" % ref) # END try commit attribute # typecheck if obj is not None and self._points_to_commits_only and obj.type != Commit.type: raise TypeError("Require commit, got %r" % obj) # END verify type oldbinsha = None if logmsg is not None: try: oldbinsha = self.commit.binsha except ValueError: oldbinsha = Commit.NULL_BIN_SHA # END handle non-existing # END retrieve old hexsha fpath = self.abspath assure_directory_exists(fpath, is_file=True) lfd = LockedFD(fpath) fd = lfd.open(write=True, stream=True) fd.write(write_value) lfd.commit() # Adjust the reflog if logmsg is not None: self.log_append(oldbinsha, logmsg) # END handle reflog return self
def set_reference(self, ref, logmsg=None): """Set ourselves to the given ref. It will stay a symbol if the ref is a Reference. Otherwise an Object, given as Object instance or refspec, is assumed and if valid, will be set which effectively detaches the refererence if it was a purely symbolic one. :param ref: SymbolicReference instance, Object instance or refspec string Only if the ref is a SymbolicRef instance, we will point to it. Everything else is dereferenced to obtain the actual object. :param logmsg: If set to a string, the message will be used in the reflog. Otherwise, a reflog entry is not written for the changed reference. The previous commit of the entry will be the commit we point to now. See also: log_append() :return: self :note: This symbolic reference will not be dereferenced. For that, see ``set_object(...)``""" write_value = None obj = None if isinstance(ref, SymbolicReference): write_value = "ref: %s" % ref.path elif isinstance(ref, Object): obj = ref write_value = ref.hexsha elif isinstance(ref, str): try: obj = self.repo.rev_parse(ref + "^{}") # optionally deref tags write_value = obj.hexsha except (BadObject, BadName) as e: raise ValueError("Could not extract object from %s" % ref) from e # END end try string else: raise ValueError("Unrecognized Value: %r" % ref) # END try commit attribute # typecheck if obj is not None and self._points_to_commits_only and obj.type != Commit.type: raise TypeError("Require commit, got %r" % obj) # END verify type oldbinsha = None if logmsg is not None: try: oldbinsha = self.commit.binsha except ValueError: oldbinsha = Commit.NULL_BIN_SHA # END handle non-existing # END retrieve old hexsha fpath = self.abspath assure_directory_exists(fpath, is_file=True) lfd = LockedFD(fpath) fd = lfd.open(write=True, stream=True) ok = True try: fd.write(write_value.encode('ascii') + b'\n') lfd.commit() ok = True finally: if not ok: lfd.rollback() # Adjust the reflog if logmsg is not None: self.log_append(oldbinsha, logmsg) return self