Exemplo n.º 1
0
    def _create(cls, repo, path, resolve, reference, force, logmsg=None):
        """internal method used to create a new symbolic reference.
        If resolve is False, the reference will be taken as is, creating
        a proper symbolic reference. Otherwise it will be resolved to the
        corresponding object and a detached symbolic reference will be created
        instead"""
        full_ref_path = cls.to_full_path(path)
        abs_ref_path = join(repo.git_dir, full_ref_path)

        # figure out target data
        target = reference
        if resolve:
            target = repo.rev_parse(str(reference))

        if not force and isfile(abs_ref_path):
            target_data = str(target)
            if isinstance(target, SymbolicReference):
                target_data = target.path
            if not resolve:
                target_data = "ref: " + target_data
            existing_data = open(abs_ref_path, 'rb').read().decode(defenc).strip()
            if existing_data != target_data:
                raise OSError("Reference at %r does already exist, pointing to %r, requested was %r" %
                              (full_ref_path, existing_data, target_data))
        # END no force handling

        ref = cls(repo, full_ref_path)
        ref.set_reference(target, logmsg)
        return ref
Exemplo n.º 2
0
    def is_dirty(self, index=True, working_tree=True, untracked_files=False,
                 submodules=True):
        """
        :return:
            ``True``, the repository is considered dirty. By default it will react
            like a git-status without untracked files, hence it is dirty if the
            index or the working copy have changes."""
        if self._bare:
            # Bare repositories with no associated working directory are
            # always consired to be clean.
            return False

        # start from the one which is fastest to evaluate
        default_args = ['--abbrev=40', '--full-index', '--raw']
        if not submodules:
            default_args.append('--ignore-submodules')
        if index:
            # diff index against HEAD
            if isfile(self.index.path) and \
                    len(self.git.diff('--cached', *default_args)):
                return True
        # END index handling
        if working_tree:
            # diff index against working tree
            if len(self.git.diff(*default_args)):
                return True
        # END working tree handling
        if untracked_files:
            if len(self._get_untracked_files(ignore_submodules=not submodules)):
                return True
        # END untracked files
        return False
Exemplo n.º 3
0
def is_git_dir(d):
    """ This is taken from the git setup.c:is_git_directory
	function."""
    if isdir(d) and isdir(join(d, "objects")) and isdir(join(d, "refs")):
        headref = join(d, "HEAD")
        return isfile(headref) or (os.path.islink(headref) and os.readlink(headref).startswith("refs"))
    return False
Exemplo n.º 4
0
    def _create(cls, repo, path, resolve, reference, force, logmsg=None):
        """internal method used to create a new symbolic reference.
        If resolve is False, the reference will be taken as is, creating
        a proper symbolic reference. Otherwise it will be resolved to the
        corresponding object and a detached symbolic reference will be created
        instead"""
        full_ref_path = cls.to_full_path(path)
        abs_ref_path = join(repo.git_dir, full_ref_path)

        # figure out target data
        target = reference
        if resolve:
            target = repo.rev_parse(str(reference))

        if not force and isfile(abs_ref_path):
            target_data = str(target)
            if isinstance(target, SymbolicReference):
                target_data = target.path
            if not resolve:
                target_data = "ref: " + target_data
            existing_data = open(abs_ref_path,
                                 'rb').read().decode(defenc).strip()
            if existing_data != target_data:
                raise OSError(
                    "Reference at %r does already exist, pointing to %r, requested was %r"
                    % (full_ref_path, existing_data, target_data))
        # END no force handling

        ref = cls(repo, full_ref_path)
        ref.set_reference(target, logmsg)
        return ref
Exemplo n.º 5
0
def is_git_dir(d):
    """ This is taken from the git setup.c:is_git_directory
    function.

    @throws WorkTreeRepositoryUnsupported if it sees a worktree directory. It's quite hacky to do that here,
            but at least clearly indicates that we don't support it.
            There is the unlikely danger to throw if we see directories which just look like a worktree dir,
            but are none."""
    if isdir(d):
        if isdir(join(d, 'objects')) and isdir(join(d, 'refs')):
            headref = join(d, 'HEAD')
            return isfile(headref) or \
                (os.path.islink(headref) and
                 os.readlink(headref).startswith('refs'))
        elif isfile(join(d, 'gitdir')) and isfile(join(d, 'commondir')) and isfile(join(d, 'gitfile')):
            raise WorkTreeRepositoryUnsupported(d)
    return False
Exemplo n.º 6
0
def find_git_dir(d):
    if is_git_dir(d):
        return d
    elif isfile(d):
        with open(d) as fp:
            content = fp.read().rstrip()
        if content.startswith('gitdir: '):
            d = join(dirname(d), content[8:])
            return find_git_dir(d)
    return None
Exemplo n.º 7
0
def is_git_dir(d):
    """ This is taken from the git setup.c:is_git_directory
	function."""
    if isdir(d) and \
      isdir(join(d, 'objects')) and \
      isdir(join(d, 'refs')):
        headref = join(d, 'HEAD')
        return isfile(headref) or \
          (os.path.islink(headref) and
          os.readlink(headref).startswith('refs'))
    return False
Exemplo n.º 8
0
def is_git_dir(d):
    """ This is taken from the git setup.c:is_git_directory
    function."""
    if isdir(d) and \
            isdir(join(d, 'objects')) and \
            isdir(join(d, 'refs')):
        headref = join(d, 'HEAD')
        return isfile(headref) or \
               (os.path.islink(headref) and
                os.readlink(headref).startswith('refs'))
    return False
Exemplo n.º 9
0
    def rename(self, new_path, force=False):
        """Rename self to a new path

        :param new_path:
            Either a simple name or a full path, i.e. new_name or features/new_name.
            The prefix refs/ is implied for references and will be set as needed.
            In case this is a symbolic ref, there is no implied prefix

        :param force:
            If True, the rename will succeed even if a head with the target name
            already exists. It will be overwritten in that case

        :return: self
        :raise OSError: In case a file at path but a different contents already exists """
        new_path = self.to_full_path(new_path)
        if self.path == new_path:
            return self

        new_abs_path = join(self.repo.git_dir, new_path)
        cur_abs_path = join(self.repo.git_dir, self.path)
        if isfile(new_abs_path):
            if not force:
                # if they point to the same file, its not an error
                with open(new_abs_path, 'rb') as fd1:
                    f1 = fd1.read().strip()
                with open(cur_abs_path, 'rb') as fd2:
                    f2 = fd2.read().strip()
                if f1 != f2:
                    raise OSError("File at path %r already exists" %
                                  new_abs_path)
                # else: we could remove ourselves and use the otherone, but
                # but clarity we just continue as usual
            # END not force handling
            os.remove(new_abs_path)
        # END handle existing target file

        dname = dirname(new_abs_path)
        if not isdir(dname):
            os.makedirs(dname)
        # END create directory

        rename(cur_abs_path, new_abs_path)
        self.path = new_path

        return self
Exemplo n.º 10
0
    def _set_alternates(self, alts):
        """Sets the alternates

        :parm alts:
            is the array of string paths representing the alternates at which
            git should look for objects, i.e. /home/user/repo/.git/objects

        :raise NoSuchPathError:
        :note:
            The method does not check for the existance of the paths in alts
            as the caller is responsible."""
        alternates_path = join(self.git_dir, 'objects', 'info', 'alternates')
        if not alts:
            if isfile(alternates_path):
                os.remove(alternates_path)
        else:
            with open(alternates_path, 'wb') as f:
                f.write("\n".join(alts).encode(defenc))
Exemplo n.º 11
0
    def rename(self, new_path, force=False):
        """Rename self to a new path

        :param new_path:
            Either a simple name or a full path, i.e. new_name or features/new_name.
            The prefix refs/ is implied for references and will be set as needed.
            In case this is a symbolic ref, there is no implied prefix

        :param force:
            If True, the rename will succeed even if a head with the target name
            already exists. It will be overwritten in that case

        :return: self
        :raise OSError: In case a file at path but a different contents already exists """
        new_path = self.to_full_path(new_path)
        if self.path == new_path:
            return self

        new_abs_path = join(self.repo.git_dir, new_path)
        cur_abs_path = join(self.repo.git_dir, self.path)
        if isfile(new_abs_path):
            if not force:
                # if they point to the same file, its not an error
                if open(new_abs_path, 'rb').read().strip() != open(cur_abs_path,
                                                                   'rb').read().strip():
                    raise OSError("File at path %r already exists" % new_abs_path)
                # else: we could remove ourselves and use the otherone, but
                # but clarity we just continue as usual
            # END not force handling
            os.remove(new_abs_path)
        # END handle existing target file

        dname = dirname(new_abs_path)
        if not isdir(dname):
            os.makedirs(dname)
        # END create directory

        rename(cur_abs_path, new_abs_path)
        self.path = new_path

        return self
Exemplo n.º 12
0
    def _set_alternates(self, alts):
        """Sets the alternates

        :parm alts:
            is the array of string paths representing the alternates at which
            git should look for objects, i.e. /home/user/repo/.git/objects

        :raise NoSuchPathError:
        :note:
            The method does not check for the existance of the paths in alts
            as the caller is responsible."""
        alternates_path = join(self.git_dir, 'objects', 'info', 'alternates')
        if not alts:
            if isfile(alternates_path):
                os.remove(alternates_path)
        else:
            try:
                f = open(alternates_path, 'wb')
                f.write("\n".join(alts).encode(defenc))
            finally:
                f.close()
Exemplo n.º 13
0
	def _set_object(self, ref):
		"""
		Set our reference to point to the given ref. It will be converted
		to a specific hexsha.
		If the reference does not exist, it will be created.
		
		:note: 
			TypeChecking is done by the git command"""
		# check for existence, touch it if required
		abs_path = self._abs_path()
		existed = True
		if not isfile(abs_path):
			existed = False
			open(abs_path, 'wb').write(Object.NULL_HEX_SHA)
		# END quick create 
		
		# do it safely by specifying the old value
		try:
			self.repo.git.update_ref(self.path, ref, (existed and self._get_object().hexsha) or None)
		except:
			if not existed:
				os.remove(abs_path)
			# END remove file on error if it didn't exist before
			raise
Exemplo n.º 14
0
    def store(self, istream):
        """note: The sha we produce will be hex by nature"""
        tmp_path = None
        writer = self.ostream()
        if writer is None:
            # open a tmp file to write the data to
            fd, tmp_path = tempfile.mkstemp(prefix="obj", dir=self._root_path)

            if istream.binsha is None:
                writer = FDCompressedSha1Writer(fd)
            else:
                writer = FDStream(fd)
            # END handle direct stream copies
        # END handle custom writer

        try:
            try:
                if istream.binsha is not None:
                    # copy as much as possible, the actual uncompressed item size might
                    # be smaller than the compressed version
                    stream_copy(istream.read, writer.write, MAXSIZE, self.stream_chunk_size)
                else:
                    # write object with header, we have to make a new one
                    write_object(
                        istream.type, istream.size, istream.read, writer.write, chunk_size=self.stream_chunk_size
                    )
                # END handle direct stream copies
            finally:
                if tmp_path:
                    writer.close()
            # END assure target stream is closed
        except:
            if tmp_path:
                os.remove(tmp_path)
            raise
        # END assure tmpfile removal on error

        hexsha = None
        if istream.binsha:
            hexsha = istream.hexsha
        else:
            hexsha = writer.sha(as_hex=True)
        # END handle sha

        if tmp_path:
            obj_path = self.db_path(self.object_path(hexsha))
            obj_dir = dirname(obj_path)
            if not isdir(obj_dir):
                mkdir(obj_dir)
            # END handle destination directory
            # rename onto existing doesn't work on windows
            if os.name == "nt":
                if isfile(obj_path):
                    remove(tmp_path)
                else:
                    rename(tmp_path, obj_path)
                # end rename only if needed
            else:
                rename(tmp_path, obj_path)
            # END handle win32

            # make sure its readable for all ! It started out as rw-- tmp file
            # but needs to be rwrr
            chmod(obj_path, self.new_objects_mode)
        # END handle dry_run

        istream.binsha = hex_to_bin(hexsha)
        return istream
Exemplo n.º 15
0
    def store(self, istream):
        """note: The sha we produce will be hex by nature"""
        tmp_path = None
        writer = self.ostream()
        if writer is None:
            # open a tmp file to write the data to
            fd, tmp_path = tempfile.mkstemp(prefix='obj', dir=self._root_path)

            if istream.binsha is None:
                writer = FDCompressedSha1Writer(fd)
            else:
                writer = FDStream(fd)
            # END handle direct stream copies
        # END handle custom writer

        try:
            try:
                if istream.binsha is not None:
                    # copy as much as possible, the actual uncompressed item size might
                    # be smaller than the compressed version
                    stream_copy(istream.read, writer.write, sys.maxint,
                                self.stream_chunk_size)
                else:
                    # write object with header, we have to make a new one
                    write_object(istream.type,
                                 istream.size,
                                 istream.read,
                                 writer.write,
                                 chunk_size=self.stream_chunk_size)
                # END handle direct stream copies
            finally:
                if tmp_path:
                    writer.close()
            # END assure target stream is closed
        except:
            if tmp_path:
                os.remove(tmp_path)
            raise
        # END assure tmpfile removal on error

        hexsha = None
        if istream.binsha:
            hexsha = istream.hexsha
        else:
            hexsha = writer.sha(as_hex=True)
        # END handle sha

        if tmp_path:
            obj_path = self.db_path(self.object_path(hexsha))
            obj_dir = dirname(obj_path)
            if not isdir(obj_dir):
                mkdir(obj_dir)
            # END handle destination directory
            # rename onto existing doesn't work on windows
            if os.name == 'nt' and isfile(obj_path):
                remove(obj_path)
            # END handle win322
            rename(tmp_path, obj_path)

            # make sure its readable for all ! It started out as rw-- tmp file
            # but needs to be rwrr
            chmod(obj_path, self.new_objects_mode)
        # END handle dry_run

        istream.binsha = hex_to_bin(hexsha)
        return istream