예제 #1
0
파일: fun.py 프로젝트: CrypticGator/rmtoo
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
예제 #2
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
예제 #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
예제 #4
0
	def _get_fetch_info_from_stderr(self, proc, progress):
		# skip first line as it is some remote info we are not interested in
		output = IterableList('name')
		
		
		# lines which are no progress are fetch info lines
		# this also waits for the command to finish
		# Skip some progress lines that don't provide relevant information
		fetch_info_lines = list()
		for line in digest_process_messages(proc.stderr, progress):
			if line.startswith('From') or line.startswith('remote: Total'):
				continue
			elif line.startswith('warning:'):
				print >> sys.stderr, line
				continue
			elif line.startswith('fatal:'):
				raise GitCommandError(("Error when fetching: %s" % line,), 2)
			# END handle special messages
			fetch_info_lines.append(line)
		# END for each line
		
		# read head information 
		fp = open(join(self.repo.git_dir, 'FETCH_HEAD'),'r')
		fetch_head_info = fp.readlines()
		fp.close()
		
		assert len(fetch_info_lines) == len(fetch_head_info), "len(%s) != len(%s)" % (fetch_head_info, fetch_info_lines)
		
		output.extend(FetchInfo._from_line(self.repo, err_line, fetch_line) 
						for err_line,fetch_line in zip(fetch_info_lines, fetch_head_info))
		
		finalize_process(proc)
		return output
예제 #5
0
    def _get_fetch_info_from_stderr(self, proc, progress):
        # skip first line as it is some remote info we are not interested in
        output = IterableList('name')

        # lines which are no progress are fetch info lines
        # this also waits for the command to finish
        # Skip some progress lines that don't provide relevant information
        fetch_info_lines = list()
        for line in self._digest_process_messages(proc.stderr, progress):
            if line.startswith('From') or line.startswith('remote: Total'):
                continue
            fetch_info_lines.append(line)
        # END for each line

        # read head information
        fp = open(join(self.repo.git_dir, 'FETCH_HEAD'), 'r')
        fetch_head_info = fp.readlines()
        fp.close()

        assert len(fetch_info_lines) == len(fetch_head_info)

        output.extend(
            FetchInfo._from_line(self.repo, err_line, fetch_line)
            for err_line, fetch_line in zip(fetch_info_lines, fetch_head_info))

        self._finalize_proc(proc)
        return output
예제 #6
0
파일: base.py 프로젝트: ReaganD/GitPython
    def _clone(cls, git, url, path, odb_default_type, progress, **kwargs):
        # special handling for windows for path at which the clone should be
        # created.
        # tilde '~' will be expanded to the HOME no matter where the ~ occours. Hence
        # we at least give a proper error instead of letting git fail
        prev_cwd = None
        prev_path = None
        odbt = kwargs.pop('odbt', odb_default_type)
        if os.name == 'nt':
            if '~' in path:
                raise OSError("Git cannot handle the ~ character in path %r correctly" % path)

            # on windows, git will think paths like c: are relative and prepend the
            # current working dir ( before it fails ). We temporarily adjust the working
            # dir to make this actually work
            match = re.match("(\w:[/\\\])(.*)", path)
            if match:
                prev_cwd = os.getcwd()
                prev_path = path
                drive, rest_of_path = match.groups()
                os.chdir(drive)
                path = rest_of_path
                kwargs['with_keep_cwd'] = True
            # END cwd preparation
        # END windows handling

        try:
            proc = git.clone(url, path, with_extended_output=True, as_process=True,
                             v=True, **add_progress(kwargs, git, progress))
            if progress:
                handle_process_output(proc, None, progress.new_message_handler(), finalize_process)
            else:
                (stdout, stderr) = proc.communicate()
                finalize_process(proc, stderr=stderr)
            # end handle progress
        finally:
            if prev_cwd is not None:
                os.chdir(prev_cwd)
                path = prev_path
            # END reset previous working dir
        # END bad windows handling

        # our git command could have a different working dir than our actual
        # environment, hence we prepend its working dir if required
        if not os.path.isabs(path) and git.working_dir:
            path = join(git._working_dir, path)

        # adjust remotes - there may be operating systems which use backslashes,
        # These might be given as initial paths, but when handling the config file
        # that contains the remote from which we were clones, git stops liking it
        # as it will escape the backslashes. Hence we undo the escaping just to be
        # sure
        repo = cls(os.path.abspath(path), odbt=odbt)
        if repo.remotes:
            writer = repo.remotes[0].config_writer
            writer.set_value('url', repo.remotes[0].url.replace("\\\\", "\\").replace("\\", "/"))
            # PY3: be sure cleanup is performed and lock is released
            writer.release()
        # END handle remote repo
        return repo
	def _get_fetch_info_from_stderr(self, proc, progress):
		# skip first line as it is some remote info we are not interested in
		output = IterableList('name')
		
		
		# lines which are no progress are fetch info lines
		# this also waits for the command to finish
		# Skip some progress lines that don't provide relevant information
		fetch_info_lines = list()
		for line in self._digest_process_messages(proc.stderr, progress):
			if line.startswith('From') or line.startswith('remote: Total'):
				continue
			fetch_info_lines.append(line)
		# END for each line
		
		# read head information 
		fp = open(join(self.repo.git_dir, 'FETCH_HEAD'),'r')
		fetch_head_info = fp.readlines()
		fp.close()
		
		assert len(fetch_info_lines) == len(fetch_head_info)
		
		output.extend(FetchInfo._from_line(self.repo, err_line, fetch_line) 
						for err_line,fetch_line in zip(fetch_info_lines, fetch_head_info))
		
		self._finalize_proc(proc)
		return output
예제 #8
0
	def _get_ref_info(cls, repo, ref_path):
		"""Return: (sha, target_ref_path) if available, the sha the file at 
		rela_path points to, or None. target_ref_path is the reference we 
		point to, or None"""
		tokens = None
		try:
			fp = open(join(repo.git_dir, ref_path), 'r')
			value = fp.read().rstrip()
			fp.close()
			tokens = value.split(" ")
		except (OSError,IOError):
			# Probably we are just packed, find our entry in the packed refs file
			# NOTE: We are not a symbolic ref if we are in a packed file, as these
			# are excluded explictly
			for sha, path in cls._iter_packed_refs(repo):
				if path != ref_path: continue
				tokens = (sha, path)
				break
			# END for each packed ref
		# END handle packed refs
		if tokens is None:
			raise ValueError("Reference at %r does not exist" % ref_path)
		
		# is it a reference ?
		if tokens[0] == 'ref:':
			return (None, tokens[1])
			
		# its a commit
		if repo.re_hexsha_only.match(tokens[0]):
			return (tokens[0], None)
			
		raise ValueError("Failed to parse reference information from %r" % ref_path)
예제 #9
0
 def path(cls, ref):
     """
     :return: string to absolute path at which the reflog of the given ref
         instance would be found. The path is not guaranteed to point to a valid
         file though.
     :param ref: SymbolicReference instance"""
     return join(ref.repo.git_dir, "logs", to_native_path(ref.path))
예제 #10
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
예제 #11
0
    def _get_fetch_info_from_stderr(self, proc, progress):
        # skip first line as it is some remote info we are not interested in
        output = IterableList('name')


        # lines which are no progress are fetch info lines
        # this also waits for the command to finish
        # Skip some progress lines that don't provide relevant information
        fetch_info_lines = list()
        for line in digest_process_messages(proc.stderr, progress):
            if line.startswith('From') or line.startswith('remote: Total'):
                continue
            elif line.startswith('warning:'):
                print >> sys.stderr, line
                continue
            elif line.startswith('fatal:'):
                raise GitCommandError(("Error when fetching: %s" % line,), 2)
            # END handle special messages
            fetch_info_lines.append(line)
        # END for each line

        # read head information
        fp = open(join(self.repo.git_dir, 'FETCH_HEAD'), 'r')
        fetch_head_info = fp.readlines()
        fp.close()

        assert len(fetch_info_lines) == len(fetch_head_info), "len(%s) != len(%s)" % (
        fetch_head_info, fetch_info_lines)

        output.extend(FetchInfo._from_line(self.repo, err_line, fetch_line)
                      for err_line, fetch_line in zip(fetch_info_lines, fetch_head_info))

        finalize_process(proc)
        return output
예제 #12
0
파일: base.py 프로젝트: john5a18/GitPython
 def _set_daemon_export(self, value):
     filename = join(self.git_dir, self.DAEMON_EXPORT_FILE)
     fileexists = os.path.exists(filename)
     if value and not fileexists:
         touch(filename)
     elif not value and fileexists:
         os.unlink(filename)
예제 #13
0
    def _get_ref_info(cls, repo, ref_path):
        """Return: (sha, target_ref_path) if available, the sha the file at
        rela_path points to, or None. target_ref_path is the reference we
        point to, or None"""
        tokens = None
        try:
            fp = open(join(repo.git_dir, ref_path), 'r')
            value = fp.read().rstrip()
            fp.close()
            tokens = value.split(" ")
        except (OSError, IOError):
            # Probably we are just packed, find our entry in the packed refs file
            # NOTE: We are not a symbolic ref if we are in a packed file, as these
            # are excluded explictly
            for sha, path in cls._iter_packed_refs(repo):
                if path != ref_path: continue
                tokens = (sha, path)
                break
            # END for each packed ref
        # END handle packed refs
        if tokens is None:
            raise ValueError("Reference at %r does not exist" % ref_path)

        # is it a reference ?
        if tokens[0] == 'ref:':
            return (None, tokens[1])

        # its a commit
        if repo.re_hexsha_only.match(tokens[0]):
            return (tokens[0], None)

        raise ValueError("Failed to parse reference information from %r" % ref_path)
예제 #14
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
예제 #15
0
파일: base.py 프로젝트: zofuthan/GitPython
 def _set_daemon_export(self, value):
     filename = join(self.git_dir, self.DAEMON_EXPORT_FILE)
     fileexists = os.path.exists(filename)
     if value and not fileexists:
         touch(filename)
     elif not value and fileexists:
         os.unlink(filename)
예제 #16
0
파일: log.py 프로젝트: dalehamel/git-kit
    def path(cls, ref):
        """
		:return: string to absolute path at which the reflog of the given ref 
			instance would be found. The path is not guaranteed to point to a valid 
			file though.
		:param ref: SymbolicReference instance"""
        return join(ref.repo.git_dir, "logs", to_native_path(ref.path))
예제 #17
0
파일: base.py 프로젝트: john5a18/GitPython
    def _clone(cls, git, url, path, odb_default_type, progress, **kwargs):
        # special handling for windows for path at which the clone should be
        # created.
        # tilde '~' will be expanded to the HOME no matter where the ~ occours. Hence
        # we at least give a proper error instead of letting git fail
        prev_cwd = None
        prev_path = None
        odbt = kwargs.pop('odbt', odb_default_type)
        if os.name == 'nt':
            if '~' in path:
                raise OSError("Git cannot handle the ~ character in path %r correctly" % path)

            # on windows, git will think paths like c: are relative and prepend the
            # current working dir ( before it fails ). We temporarily adjust the working
            # dir to make this actually work
            match = re.match("(\w:[/\\\])(.*)", path)
            if match:
                prev_cwd = os.getcwd()
                prev_path = path
                drive, rest_of_path = match.groups()
                os.chdir(drive)
                path = rest_of_path
                kwargs['with_keep_cwd'] = True
            # END cwd preparation
        # END windows handling

        try:
            proc = git.clone(url, path, with_extended_output=True, as_process=True,
                             v=True, **add_progress(kwargs, git, progress))
            if progress:
                handle_process_output(proc, None, progress.new_message_handler(), finalize_process)
            else:
                finalize_process(proc)
            # end handle progress
        finally:
            if prev_cwd is not None:
                os.chdir(prev_cwd)
                path = prev_path
            # END reset previous working dir
        # END bad windows handling

        # our git command could have a different working dir than our actual
        # environment, hence we prepend its working dir if required
        if not os.path.isabs(path) and git.working_dir:
            path = join(git._working_dir, path)

        # adjust remotes - there may be operating systems which use backslashes,
        # These might be given as initial paths, but when handling the config file
        # that contains the remote from which we were clones, git stops liking it
        # as it will escape the backslashes. Hence we undo the escaping just to be
        # sure
        repo = cls(os.path.abspath(path), odbt=odbt)
        if repo.remotes:
            writer = repo.remotes[0].config_writer
            writer.set_value('url', repo.remotes[0].url.replace("\\\\", "\\").replace("\\", "/"))
            # PY3: be sure cleanup is performed and lock is released
            writer.release()
        # END handle remote repo
        return repo
예제 #18
0
    def _get_fetch_info_from_stderr(self, proc, progress):
        progress = to_progress_instance(progress)

        # skip first line as it is some remote info we are not interested in
        output = IterableList('name')

        # lines which are no progress are fetch info lines
        # this also waits for the command to finish
        # Skip some progress lines that don't provide relevant information
        fetch_info_lines = list()
        # Basically we want all fetch info lines which appear to be in regular form, and thus have a
        # command character. Everything else we ignore,
        cmds = set(PushInfo._flag_map.keys()) & set(FetchInfo._flag_map.keys())

        progress_handler = progress.new_message_handler()

        stderr_text = None

        for line in proc.stderr:
            line = force_text(line)
            for pline in progress_handler(line):
                # END handle special messages
                for cmd in cmds:
                    if len(line) > 1 and line[0] == ' ' and line[1] == cmd:
                        fetch_info_lines.append(line)
                        continue
                    # end find command code
                # end for each comand code we know
            # end for each line progress didn't handle
        # end
        if progress.error_lines():
            stderr_text = '\n'.join(progress.error_lines())

        finalize_process(proc, stderr=stderr_text)

        # read head information
        fp = open(join(self.repo.git_dir, 'FETCH_HEAD'), 'rb')
        fetch_head_info = [l.decode(defenc) for l in fp.readlines()]
        fp.close()

        l_fil = len(fetch_info_lines)
        l_fhi = len(fetch_head_info)
        if l_fil != l_fhi:
            msg = "Fetch head lines do not match lines provided via progress information\n"
            msg += "length of progress lines %i should be equal to lines in FETCH_HEAD file %i\n"
            msg += "Will ignore extra progress lines or fetch head lines."
            msg %= (l_fil, l_fhi)
            log.debug(msg)
            if l_fil < l_fhi:
                fetch_head_info = fetch_head_info[:l_fil]
            else:
                fetch_info_lines = fetch_info_lines[:l_fhi]
            # end truncate correct list
        # end sanity check + sanitization

        output.extend(
            FetchInfo._from_line(self.repo, err_line, fetch_line)
            for err_line, fetch_line in zip(fetch_info_lines, fetch_head_info))
        return output
예제 #19
0
파일: base.py 프로젝트: john5a18/GitPython
    def _get_config_path(self, config_level):
        # we do not support an absolute path of the gitconfig on windows ,
        # use the global config instead
        if sys.platform == "win32" and config_level == "system":
            config_level = "global"

        if config_level == "system":
            return "/etc/gitconfig"
        elif config_level == "user":
            config_home = os.environ.get("XDG_CONFIG_HOME") or os.path.join(os.environ.get("HOME", '~'), ".config")
            return os.path.normpath(os.path.expanduser(join(config_home, "git", "config")))
        elif config_level == "global":
            return os.path.normpath(os.path.expanduser("~/.gitconfig"))
        elif config_level == "repository":
            return os.path.normpath(join(self.git_dir, "config"))

        raise ValueError("Invalid configuration level: %r" % config_level)
예제 #20
0
    def delete(cls, repo, path):
        """Delete the reference at the given path

        :param repo:
            Repository to delete the reference from

        :param path:
            Short or full path pointing to the reference, i.e. refs/myreference
            or just "myreference", hence 'refs/' is implied.
            Alternatively the symbolic reference to be deleted"""
        full_ref_path = cls.to_full_path(path)
        abs_path = join(repo.git_dir, full_ref_path)
        if exists(abs_path):
            os.remove(abs_path)
        else:
            # check packed refs
            pack_file_path = cls._get_packed_refs_path(repo)
            try:
                reader = open(pack_file_path, 'rb')
            except (OSError, IOError):
                pass  # it didnt exist at all
            else:
                new_lines = list()
                made_change = False
                dropped_last_line = False
                for line in reader:
                    # keep line if it is a comment or if the ref to delete is not
                    # in the line
                    # If we deleted the last line and this one is a tag-reference object,
                    # we drop it as well
                    line = line.decode(defenc)
                    if (line.startswith('#') or full_ref_path not in line) and \
                            (not dropped_last_line or dropped_last_line and not line.startswith('^')):
                        new_lines.append(line)
                        dropped_last_line = False
                        continue
                    # END skip comments and lines without our path

                    # drop this line
                    made_change = True
                    dropped_last_line = True
                # END for each line in packed refs
                reader.close()

                # write the new lines
                if made_change:
                    # write-binary is required, otherwise windows will
                    # open the file in text mode and change LF to CRLF !
                    open(pack_file_path,
                         'wb').writelines(l.encode(defenc) for l in new_lines)
                # END write out file
            # END open exception handling
        # END handle deletion

        # delete the reflog
        reflog_path = RefLog.path(cls(repo, full_ref_path))
        if os.path.isfile(reflog_path):
            os.remove(reflog_path)
예제 #21
0
파일: remote.py 프로젝트: shimo85/GitPython
    def _get_fetch_info_from_stderr(self, proc, progress):
        progress = to_progress_instance(progress)

        # skip first line as it is some remote info we are not interested in
        output = IterableList('name')

        # lines which are no progress are fetch info lines
        # this also waits for the command to finish
        # Skip some progress lines that don't provide relevant information
        fetch_info_lines = list()
        # Basically we want all fetch info lines which appear to be in regular form, and thus have a
        # command character. Everything else we ignore,
        cmds = set(PushInfo._flag_map.keys()) & set(FetchInfo._flag_map.keys())

        progress_handler = progress.new_message_handler()

        stderr_text = None

        for line in proc.stderr:
            line = force_text(line)
            for pline in progress_handler(line):
                # END handle special messages
                for cmd in cmds:
                    if len(line) > 1 and line[0] == ' ' and line[1] == cmd:
                        fetch_info_lines.append(line)
                        continue
                    # end find command code
                # end for each comand code we know
            # end for each line progress didn't handle
        # end
        if progress.error_lines():
            stderr_text = '\n'.join(progress.error_lines())
            
        finalize_process(proc, stderr=stderr_text)

        # read head information
        fp = open(join(self.repo.git_dir, 'FETCH_HEAD'), 'rb')
        fetch_head_info = [l.decode(defenc) for l in fp.readlines()]
        fp.close()

        l_fil = len(fetch_info_lines)
        l_fhi = len(fetch_head_info)
        if l_fil != l_fhi:
            msg = "Fetch head lines do not match lines provided via progress information\n"
            msg += "length of progress lines %i should be equal to lines in FETCH_HEAD file %i\n"
            msg += "Will ignore extra progress lines or fetch head lines."
            msg %= (l_fil, l_fhi)
            log.debug(msg)
            if l_fil < l_fhi:
                fetch_head_info = fetch_head_info[:l_fil]
            else:
                fetch_info_lines = fetch_info_lines[:l_fhi]
            # end truncate correct list
        # end sanity check + sanitization
        
        output.extend(FetchInfo._from_line(self.repo, err_line, fetch_line)
                      for err_line, fetch_line in zip(fetch_info_lines, fetch_head_info))
        return output
예제 #22
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
예제 #23
0
    def delete(cls, repo, path):
        """Delete the reference at the given path

        :param repo:
            Repository to delete the reference from

        :param path:
            Short or full path pointing to the reference, i.e. refs/myreference
            or just "myreference", hence 'refs/' is implied.
            Alternatively the symbolic reference to be deleted"""
        full_ref_path = cls.to_full_path(path)
        abs_path = join(repo.git_dir, full_ref_path)
        if exists(abs_path):
            os.remove(abs_path)
        else:
            # check packed refs
            pack_file_path = cls._get_packed_refs_path(repo)
            try:
                reader = open(pack_file_path, 'rb')
            except (OSError, IOError):
                pass  # it didnt exist at all
            else:
                new_lines = list()
                made_change = False
                dropped_last_line = False
                for line in reader:
                    # keep line if it is a comment or if the ref to delete is not
                    # in the line
                    # If we deleted the last line and this one is a tag-reference object,
                    # we drop it as well
                    line = line.decode(defenc)
                    if (line.startswith('#') or full_ref_path not in line) and \
                            (not dropped_last_line or dropped_last_line and not line.startswith('^')):
                        new_lines.append(line)
                        dropped_last_line = False
                        continue
                    # END skip comments and lines without our path

                    # drop this line
                    made_change = True
                    dropped_last_line = True
                # END for each line in packed refs
                reader.close()

                # write the new lines
                if made_change:
                    # write-binary is required, otherwise windows will
                    # open the file in text mode and change LF to CRLF !
                    open(pack_file_path, 'wb').writelines(l.encode(defenc) for l in new_lines)
                # END write out file
            # END open exception handling
        # END handle deletion

        # delete the reflog
        reflog_path = RefLog.path(cls(repo, full_ref_path))
        if os.path.isfile(reflog_path):
            os.remove(reflog_path)
예제 #24
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
    def _get_fetch_info_from_stderr(self, proc, progress):
        # skip first line as it is some remote info we are not interested in
        # TODO: Use poll() to process stdout and stderr at same time
        output = IterableList('name')

        # lines which are no progress are fetch info lines
        # this also waits for the command to finish
        # Skip some progress lines that don't provide relevant information
        fetch_info_lines = list()
        # Basically we want all fetch info lines which appear to be in regular form, and thus have a
        # command character. Everything else we ignore,
        cmds = set(PushInfo._flag_map.keys()) & set(FetchInfo._flag_map.keys())

        progress_handler = progress.new_message_handler()

        for line in proc.stderr:
            line = line.decode(defenc)
            line = line.rstrip()
            for pline in progress_handler(line):
                if line.startswith('fatal:'):
                    raise GitCommandError(("Error when fetching: %s" % line, ),
                                          2)
                # END handle special messages
                for cmd in cmds:
                    if len(line) > 1 and line[0] == ' ' and line[1] == cmd:
                        fetch_info_lines.append(line)
                        continue
                    # end find command code
                # end for each comand code we know
            # end for each line progress didn't handle
        # end

        # We are only interested in stderr here ...
        try:
            finalize_process(proc)
        except Exception:
            if len(fetch_info_lines) == 0:
                raise
        # end exception handler

        # read head information
        fp = open(join(self.repo.git_dir, 'FETCH_HEAD'), 'rb')
        fetch_head_info = [l.decode(defenc) for l in fp.readlines()]
        fp.close()

        # NOTE: We assume to fetch at least enough progress lines to allow matching each fetch head line with it.
        assert len(fetch_info_lines) >= len(
            fetch_head_info), "len(%s) <= len(%s)" % (fetch_head_info,
                                                      fetch_info_lines)

        output.extend(
            FetchInfo._from_line(self.repo, err_line, fetch_line)
            for err_line, fetch_line in zip(fetch_info_lines, fetch_head_info))
        return output
예제 #26
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
예제 #27
0
    def _get_alternates(self):
        """The list of alternates for this repo from which objects can be retrieved

        :return: list of strings being pathnames of alternates"""
        alternates_path = join(self.git_dir, 'objects', 'info', 'alternates')

        if os.path.exists(alternates_path):
            with open(alternates_path, 'rb') as f:
                alts = f.read().decode(defenc)
            return alts.strip().splitlines()
        else:
            return list()
예제 #28
0
    def _get_fetch_info_from_stderr(self, proc, progress):
        # skip first line as it is some remote info we are not interested in
        # TODO: Use poll() to process stdout and stderr at same time
        output = IterableList('name')

        # lines which are no progress are fetch info lines
        # this also waits for the command to finish
        # Skip some progress lines that don't provide relevant information
        fetch_info_lines = list()
        # Basically we want all fetch info lines which appear to be in regular form, and thus have a
        # command character. Everything else we ignore,
        cmds = set(PushInfo._flag_map.keys()) & set(FetchInfo._flag_map.keys())

        progress_handler = progress.new_message_handler()

        for line in proc.stderr:
            line = line.decode(defenc)
            line = line.rstrip()
            for pline in progress_handler(line):
                if line.startswith('fatal:') or line.startswith('error:'):
                    raise GitCommandError(("Error when fetching: %s" % line,), 2)
                # END handle special messages
                for cmd in cmds:
                    if len(line) > 1 and line[0] == ' ' and line[1] == cmd:
                        fetch_info_lines.append(line)
                        continue
                    # end find command code
                # end for each comand code we know
            # end for each line progress didn't handle
        # end

        # We are only interested in stderr here ...
        try:
            finalize_process(proc)
        except Exception:
            if len(fetch_info_lines) == 0:
                raise
        # end exception handler

        # read head information
        fp = open(join(self.repo.git_dir, 'FETCH_HEAD'), 'rb')
        fetch_head_info = [l.decode(defenc) for l in fp.readlines()]
        fp.close()

        # NOTE: We assume to fetch at least enough progress lines to allow matching each fetch head line with it.
        assert len(fetch_info_lines) >= len(fetch_head_info), "len(%s) <= len(%s)" % (fetch_head_info,
                                                                                      fetch_info_lines)

        output.extend(FetchInfo._from_line(self.repo, err_line, fetch_line)
                      for err_line, fetch_line in zip(fetch_info_lines, fetch_head_info))
        return output
예제 #29
0
    def _get_config_path(self, config_level):
        # we do not support an absolute path of the gitconfig on windows ,
        # use the global config instead
        if sys.platform == "win32" and config_level == "system":
            config_level = "global"

        if config_level == "system":
            return "/etc/gitconfig"
        elif config_level == "global":
            return os.path.normpath(os.path.expanduser("~/.gitconfig"))
        elif config_level == "repository":
            return join(self.git_dir, "config")

        raise ValueError("Invalid configuration level: %r" % config_level)
예제 #30
0
파일: base.py 프로젝트: 2flcastro/ka-lite
	def _get_config_path(self, config_level ):
		# we do not support an absolute path of the gitconfig on windows , 
		# use the global config instead
		if sys.platform == "win32" and config_level == "system":
			config_level = "global"
			
		if config_level == "system":
			return "/etc/gitconfig"
		elif config_level == "global":
			return os.path.normpath(os.path.expanduser("~/.gitconfig"))
		elif config_level == "repository":
			return join(self.git_dir, "config")
		
		raise ValueError( "Invalid configuration level: %r" % config_level )
예제 #31
0
    def delete(cls, repo, *refs, **kwargs):
        """Delete the given remote references.
		:note:
			kwargs are given for compatability with the base class method as we 
			should not narrow the signature."""
        repo.git.branch("-d", "-r", *refs)
        # the official deletion method will ignore remote symbolic refs - these
        # are generally ignored in the refs/ folder. We don't though
        # and delete remainders manually
        for ref in refs:
            try:
                os.remove(join(repo.git_dir, ref.path))
            except OSError:
                pass
예제 #32
0
    def _get_alternates(self):
        """The list of alternates for this repo from which objects can be retrieved

		:return: list of strings being pathnames of alternates"""
        alternates_path = join(self.git_dir, 'objects', 'info', 'alternates')

        if os.path.exists(alternates_path):
            try:
                f = open(alternates_path)
                alts = f.read()
            finally:
                f.close()
            return alts.strip().splitlines()
        else:
            return list()
예제 #33
0
파일: base.py 프로젝트: john5a18/GitPython
    def _get_alternates(self):
        """The list of alternates for this repo from which objects can be retrieved

        :return: list of strings being pathnames of alternates"""
        alternates_path = join(self.git_dir, 'objects', 'info', 'alternates')

        if os.path.exists(alternates_path):
            try:
                f = open(alternates_path, 'rb')
                alts = f.read().decode(defenc)
            finally:
                f.close()
            return alts.strip().splitlines()
        else:
            return list()
예제 #34
0
파일: fun.py 프로젝트: Javex/GitPython
def find_git_dir(d):
    if is_git_dir(d):
        return d

    try:
        with open(d) as fp:
            content = fp.read().rstrip()
    except (IOError, OSError):
        # it's probably not a file
        pass
    else:
        if content.startswith('gitdir: '):
            path = content[8:]
            if not os.path.isabs(path):
                path = join(dirname(d), path)
            return find_git_dir(path)
    # end handle exception
    return None
예제 #35
0
def find_git_dir(d):
    if is_git_dir(d):
        return d

    try:
        with open(d) as fp:
            content = fp.read().rstrip()
    except (IOError, OSError):
        # it's probably not a file
        pass
    else:
        if content.startswith('gitdir: '):
            path = content[8:]
            if not os.path.isabs(path):
                path = join(dirname(d), path)
            return find_git_dir(path)
    # end handle exception
    return None
예제 #36
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))
예제 #37
0
    def _clone(cls, git, url, path, odb_default_type, **kwargs):
        # special handling for windows for path at which the clone should be
        # created.
        # tilde '~' will be expanded to the HOME no matter where the ~ occours. Hence
        # we at least give a proper error instead of letting git fail
        prev_cwd = None
        prev_path = None
        odbt = kwargs.pop('odbt', odb_default_type)
        if os.name == 'nt':
            if '~' in path:
                raise OSError(
                    "Git cannot handle the ~ character in path %r correctly" %
                    path)

            # on windows, git will think paths like c: are relative and prepend the
            # current working dir ( before it fails ). We temporarily adjust the working
            # dir to make this actually work
            match = re.match("(\w:[/\\\])(.*)", path)
            if match:
                prev_cwd = os.getcwd()
                prev_path = path
                drive, rest_of_path = match.groups()
                os.chdir(drive)
                path = rest_of_path
                kwargs['with_keep_cwd'] = True
            # END cwd preparation
        # END windows handling

        try:
            git.clone(url, path, **kwargs)
        finally:
            if prev_cwd is not None:
                os.chdir(prev_cwd)
                path = prev_path
            # END reset previous working dir
        # END bad windows handling

        # our git command could have a different working dir than our actual
        # environment, hence we prepend its working dir if required
        if not os.path.isabs(path) and git.working_dir:
            path = join(git._working_dir, path)
        return cls(os.path.abspath(path), odbt=odbt)
예제 #38
0
파일: base.py 프로젝트: john5a18/GitPython
    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()
예제 #39
0
	def _clone(cls, git, url, path, odb_default_type, **kwargs):
		# special handling for windows for path at which the clone should be 
		# created.
		# tilde '~' will be expanded to the HOME no matter where the ~ occours. Hence
		# we at least give a proper error instead of letting git fail
		prev_cwd = None
		prev_path = None
		odbt = kwargs.pop('odbt', odb_default_type)
		if os.name == 'nt':
			if '~' in path:
				raise OSError("Git cannot handle the ~ character in path %r correctly" % path)
				
			# on windows, git will think paths like c: are relative and prepend the 
			# current working dir ( before it fails ). We temporarily adjust the working 
			# dir to make this actually work
			match = re.match("(\w:[/\\\])(.*)", path)
			if match:
				prev_cwd = os.getcwd()
				prev_path = path
				drive, rest_of_path = match.groups()
				os.chdir(drive)
				path = rest_of_path
				kwargs['with_keep_cwd'] = True
			# END cwd preparation 
		# END windows handling 
		
		try:
			git.clone(url, path, **kwargs)
		finally:
			if prev_cwd is not None:
				os.chdir(prev_cwd)
				path = prev_path
			# END reset previous working dir
		# END bad windows handling
		
		# our git command could have a different working dir than our actual 
		# environment, hence we prepend its working dir if required
		if not os.path.isabs(path) and git.working_dir:
			path = join(git._working_dir, path)
		return cls(os.path.abspath(path), odbt = odbt)
예제 #40
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
예제 #41
0
    def _get_ref_info(cls, repo, ref_path):
        """Return: (str(sha), str(target_ref_path)) if available, the sha the file at
        rela_path points to, or None. target_ref_path is the reference we
        point to, or None"""
        tokens = None
        try:
            fp = open(join(repo.git_dir, ref_path), 'rt')
            value = fp.read().rstrip()
            fp.close()
            # Don't only split on spaces, but on whitespace, which allows to parse lines like
            # 60b64ef992065e2600bfef6187a97f92398a9144                branch 'master' of git-server:/path/to/repo
            tokens = value.split()
            assert (len(tokens) != 0)
        except (OSError, IOError):
            # Probably we are just packed, find our entry in the packed refs file
            # NOTE: We are not a symbolic ref if we are in a packed file, as these
            # are excluded explictly
            for sha, path in cls._iter_packed_refs(repo):
                if path != ref_path:
                    continue
                # sha will be used
                tokens = sha, path
                break
            # END for each packed ref
        # END handle packed refs
        if tokens is None:
            raise ValueError("Reference at %r does not exist" % ref_path)

        # is it a reference ?
        if tokens[0] == 'ref:':
            return (None, tokens[1])

        # its a commit
        if repo.re_hexsha_only.match(tokens[0]):
            return (tokens[0], None)

        raise ValueError("Failed to parse reference information from %r" %
                         ref_path)
예제 #42
0
    def _clone(cls, git, url, path, odb_default_type, progress, **kwargs):
        if progress is not None:
            progress = to_progress_instance(progress)

        odbt = kwargs.pop('odbt', odb_default_type)
        proc = git.clone(url,
                         path,
                         with_extended_output=True,
                         as_process=True,
                         v=True,
                         **add_progress(kwargs, git, progress))
        if progress:
            handle_process_output(proc, None, progress.new_message_handler(),
                                  finalize_process)
        else:
            (stdout, stderr
             ) = proc.communicate()  # FIXME: Will block of outputs are big!
            log.debug("Cmd(%s)'s unused stdout: %s", getattr(proc, 'args', ''),
                      stdout)
            finalize_process(proc, stderr=stderr)

        # our git command could have a different working dir than our actual
        # environment, hence we prepend its working dir if required
        if not os.path.isabs(path) and git.working_dir:
            path = join(git._working_dir, path)

        # adjust remotes - there may be operating systems which use backslashes,
        # These might be given as initial paths, but when handling the config file
        # that contains the remote from which we were clones, git stops liking it
        # as it will escape the backslashes. Hence we undo the escaping just to be
        # sure
        repo = cls(path, odbt=odbt)
        if repo.remotes:
            with repo.remotes[0].config_writer as writer:
                writer.set_value('url', Git.polish_url(repo.remotes[0].url))
        # END handle remote repo
        return repo
예제 #43
0
    def _get_ref_info(cls, repo, ref_path):
        """Return: (str(sha), str(target_ref_path)) if available, the sha the file at
        rela_path points to, or None. target_ref_path is the reference we
        point to, or None"""
        tokens = None
        try:
            fp = open(join(repo.git_dir, ref_path), 'rt')
            value = fp.read().rstrip()
            fp.close()
            # Don't only split on spaces, but on whitespace, which allows to parse lines like
            # 60b64ef992065e2600bfef6187a97f92398a9144                branch 'master' of git-server:/path/to/repo
            tokens = value.split()
            assert(len(tokens) != 0)
        except (OSError, IOError):
            # Probably we are just packed, find our entry in the packed refs file
            # NOTE: We are not a symbolic ref if we are in a packed file, as these
            # are excluded explictly
            for sha, path in cls._iter_packed_refs(repo):
                if path != ref_path:
                    continue
                # sha will be used
                tokens = sha, path
                break
            # END for each packed ref
        # END handle packed refs
        if tokens is None:
            raise ValueError("Reference at %r does not exist" % ref_path)

        # is it a reference ?
        if tokens[0] == 'ref:':
            return (None, tokens[1])

        # its a commit
        if repo.re_hexsha_only.match(tokens[0]):
            return (tokens[0], None)

        raise ValueError("Failed to parse reference information from %r" % ref_path)
예제 #44
0
    def _get_fetch_info_from_stderr(self, proc, progress):
        # skip first line as it is some remote info we are not interested in
        output = IterableList('name')

        # lines which are no progress are fetch info lines
        # this also waits for the command to finish
        # Skip some progress lines that don't provide relevant information
        fetch_info_lines = list()
        for line in digest_process_messages(proc.stderr, progress):
            if line.startswith('From') or line.startswith('remote: Total') or line.startswith('POST') \
                    or line.startswith(' ='):
                continue
            elif line.startswith('warning:'):
                print >> sys.stderr, line
                continue
            elif line.startswith('fatal:'):
                raise GitCommandError(("Error when fetching: %s" % line, ), 2)
            # END handle special messages
            fetch_info_lines.append(line)
        # END for each line

        # read head information
        fp = open(join(self.repo.git_dir, 'FETCH_HEAD'), 'r')
        fetch_head_info = fp.readlines()
        fp.close()

        # NOTE: HACK Just disabling this line will make github repositories work much better.
        # I simply couldn't stand it anymore, so here is the quick and dirty fix ... .
        # This project needs a lot of work !
        # assert len(fetch_info_lines) == len(fetch_head_info), "len(%s) != len(%s)" % (fetch_head_info, fetch_info_lines)

        output.extend(
            FetchInfo._from_line(self.repo, err_line, fetch_line)
            for err_line, fetch_line in zip(fetch_info_lines, fetch_head_info))

        finalize_process(proc)
        return output
예제 #45
0
파일: base.py 프로젝트: zofuthan/GitPython
 def _get_daemon_export(self):
     filename = join(self.git_dir, self.DAEMON_EXPORT_FILE)
     return os.path.exists(filename)
예제 #46
0
파일: base.py 프로젝트: zofuthan/GitPython
 def _set_description(self, descr):
     filename = join(self.git_dir, 'description')
     open(filename, 'wb').write((descr + '\n').encode(defenc))
예제 #47
0
파일: base.py 프로젝트: zofuthan/GitPython
 def _get_description(self):
     filename = join(self.git_dir, 'description')
     return open(filename, 'rb').read().rstrip().decode(defenc)
예제 #48
0
파일: base.py 프로젝트: 2flcastro/ka-lite
	def __init__(self, path=None, odbt = DefaultDBType):
		"""Create a new Repo instance

		:param path: is the path to either the root git directory or the bare git repo::

			repo = Repo("/Users/mtrier/Development/git-python")
			repo = Repo("/Users/mtrier/Development/git-python.git")
			repo = Repo("~/Development/git-python.git")
			repo = Repo("$REPOSITORIES/Development/git-python.git")
		
		:param odbt: Object DataBase type - a type which is constructed by providing 
			the directory containing the database objects, i.e. .git/objects. It will
			be used to access all object data
		:raise InvalidGitRepositoryError:
		:raise NoSuchPathError:
		:return: git.Repo """
		epath = os.path.abspath(os.path.expandvars(os.path.expanduser(path or os.getcwd())))

		if not os.path.exists(epath):
			raise NoSuchPathError(epath)

		self.working_dir = None
		self._working_tree_dir = None
		self.git_dir = None
		curpath = epath
		
		# walk up the path to find the .git dir
		while curpath:
			if is_git_dir(curpath):
				self.git_dir = curpath
				self._working_tree_dir = os.path.dirname(curpath)
				break
			gitpath = join(curpath, '.git')
			if is_git_dir(gitpath):
				self.git_dir = gitpath
				self._working_tree_dir = curpath
				break
			curpath, dummy = os.path.split(curpath)
			if not dummy:
				break
		# END while curpath
		
		if self.git_dir is None:
		   raise InvalidGitRepositoryError(epath)

		self._bare = False
		try:
			self._bare = self.config_reader("repository").getboolean('core','bare') 
		except Exception:
			# lets not assume the option exists, although it should
			pass

		# adjust the wd in case we are actually bare - we didn't know that 
		# in the first place
		if self._bare:
			self._working_tree_dir = None
		# END working dir handling
		
		self.working_dir = self._working_tree_dir or self.git_dir
		self.git = Git(self.working_dir)
		
		# special handling, in special times
		args = [join(self.git_dir, 'objects')]
		if issubclass(odbt, GitCmdObjectDB):
			args.append(self.git)
		self.odb = odbt(*args)
예제 #49
0
 def object_path(self, hexsha):
     """
     :return: path at which the object with the given hexsha would be stored,
         relative to the database root"""
     return join(hexsha[:2], hexsha[2:])
예제 #50
0
 def _get_packed_refs_path(cls, repo):
     return join(repo.git_dir, 'packed-refs')
예제 #51
0
파일: base.py 프로젝트: john5a18/GitPython
 def _get_daemon_export(self):
     filename = join(self.git_dir, self.DAEMON_EXPORT_FILE)
     return os.path.exists(filename)
	def _from_line(cls, repo, line, fetch_line):
		"""Parse information from the given line as returned by git-fetch -v
		and return a new FetchInfo object representing this information.
		
		We can handle a line as follows
		"%c %-*s %-*s -> %s%s"
		
		Where c is either ' ', !, +, -, *, or =
		! means error
		+ means success forcing update
		- means a tag was updated
		* means birth of new branch or tag
		= means the head was up to date ( and not moved )
		' ' means a fast-forward
		
		fetch line is the corresponding line from FETCH_HEAD, like
		acb0fa8b94ef421ad60c8507b634759a472cd56c	not-for-merge	branch '0.1.7RC' of /tmp/tmpya0vairemote_repo"""
		match = cls.re_fetch_result.match(line)
		if match is None:
			raise ValueError("Failed to parse line: %r" % line)
			
		# parse lines
		control_character, operation, local_remote_ref, remote_local_ref, note = match.groups()
		try:
			new_hex_sha, fetch_operation, fetch_note = fetch_line.split("\t")
			ref_type_name, fetch_note = fetch_note.split(' ', 1)
		except ValueError:	# unpack error
			raise ValueError("Failed to parse FETCH__HEAD line: %r" % fetch_line)
		
		# handle FETCH_HEAD and figure out ref type
		# If we do not specify a target branch like master:refs/remotes/origin/master, 
		# the fetch result is stored in FETCH_HEAD which destroys the rule we usually
		# have. In that case we use a symbolic reference which is detached 
		ref_type = None
		if remote_local_ref == "FETCH_HEAD":
			ref_type = SymbolicReference
		elif ref_type_name	== "branch":
			ref_type = RemoteReference
		elif ref_type_name == "tag":
			ref_type = TagReference
		else:
			raise TypeError("Cannot handle reference type: %r" % ref_type_name)
			
		# create ref instance
		if ref_type is SymbolicReference:
			remote_local_ref = ref_type(repo, "FETCH_HEAD") 
		else:
			remote_local_ref = Reference.from_path(repo, join(ref_type._common_path_default, remote_local_ref.strip()))
		# END create ref instance 
		
		note = ( note and note.strip() ) or ''
		
		# parse flags from control_character
		flags = 0
		try:
			flags |= cls._flag_map[control_character]
		except KeyError:
			raise ValueError("Control character %r unknown as parsed from line %r" % (control_character, line))
		# END control char exception hanlding 
		
		# parse operation string for more info - makes no sense for symbolic refs
		old_commit = None
		if isinstance(remote_local_ref, Reference):
			if 'rejected' in operation:
				flags |= cls.REJECTED
			if 'new tag' in operation:
				flags |= cls.NEW_TAG
			if 'new branch' in operation:
				flags |= cls.NEW_HEAD
			if '...' in operation or '..' in operation:
				split_token = '...'
				if control_character == ' ':
					split_token = split_token[:-1]
				old_commit = repo.rev_parse(operation.split(split_token)[0])
			# END handle refspec
		# END reference flag handling
		
		return cls(remote_local_ref, flags, note, old_commit)
예제 #53
0
파일: base.py 프로젝트: john5a18/GitPython
 def _set_description(self, descr):
     filename = join(self.git_dir, 'description')
     open(filename, 'wb').write((descr + '\n').encode(defenc))
예제 #54
0
파일: base.py 프로젝트: john5a18/GitPython
 def _get_description(self):
     filename = join(self.git_dir, 'description')
     return open(filename, 'rb').read().rstrip().decode(defenc)
예제 #55
0
파일: base.py 프로젝트: john5a18/GitPython
    def __init__(self, path=None, odbt=DefaultDBType, search_parent_directories=False):
        """Create a new Repo instance

        :param path:
            the path to either the root git directory or the bare git repo::

                repo = Repo("/Users/mtrier/Development/git-python")
                repo = Repo("/Users/mtrier/Development/git-python.git")
                repo = Repo("~/Development/git-python.git")
                repo = Repo("$REPOSITORIES/Development/git-python.git")

        :param odbt:
            Object DataBase type - a type which is constructed by providing
            the directory containing the database objects, i.e. .git/objects. It will
            be used to access all object data
        :param search_parent_directories:
            if True, all parent directories will be searched for a valid repo as well.

            Please note that this was the default behaviour in older versions of GitPython,
            which is considered a bug though.
        :raise InvalidGitRepositoryError:
        :raise NoSuchPathError:
        :return: git.Repo """
        epath = _expand_path(path or os.getcwd())
        self.git = None  # should be set for __del__ not to fail in case we raise
        if not os.path.exists(epath):
            raise NoSuchPathError(epath)

        self.working_dir = None
        self._working_tree_dir = None
        self.git_dir = None
        curpath = epath

        # walk up the path to find the .git dir
        while curpath:
            # ABOUT os.path.NORMPATH
            # It's important to normalize the paths, as submodules will otherwise initialize their
            # repo instances with paths that depend on path-portions that will not exist after being
            # removed. It's just cleaner.
            if is_git_dir(curpath):
                self.git_dir = os.path.normpath(curpath)
                self._working_tree_dir = os.path.dirname(self.git_dir)
                break

            gitpath = find_git_dir(join(curpath, '.git'))
            if gitpath is not None:
                self.git_dir = os.path.normpath(gitpath)
                self._working_tree_dir = curpath
                break

            if not search_parent_directories:
                break
            curpath, dummy = os.path.split(curpath)
            if not dummy:
                break
        # END while curpath

        if self.git_dir is None:
            raise InvalidGitRepositoryError(epath)

        self._bare = False
        try:
            self._bare = self.config_reader("repository").getboolean('core', 'bare')
        except Exception:
            # lets not assume the option exists, although it should
            pass

        # adjust the wd in case we are actually bare - we didn't know that
        # in the first place
        if self._bare:
            self._working_tree_dir = None
        # END working dir handling

        self.working_dir = self._working_tree_dir or self.git_dir
        self.git = self.GitCommandWrapperType(self.working_dir)

        # special handling, in special times
        args = [join(self.git_dir, 'objects')]
        if issubclass(odbt, GitCmdObjectDB):
            args.append(self.git)
        self.odb = odbt(*args)
예제 #56
0
파일: base.py 프로젝트: zofuthan/GitPython
    def __init__(self,
                 path=None,
                 odbt=DefaultDBType,
                 search_parent_directories=False):
        """Create a new Repo instance

        :param path:
            the path to either the root git directory or the bare git repo::

                repo = Repo("/Users/mtrier/Development/git-python")
                repo = Repo("/Users/mtrier/Development/git-python.git")
                repo = Repo("~/Development/git-python.git")
                repo = Repo("$REPOSITORIES/Development/git-python.git")

        :param odbt:
            Object DataBase type - a type which is constructed by providing
            the directory containing the database objects, i.e. .git/objects. It will
            be used to access all object data
        :param search_parent_directories:
            if True, all parent directories will be searched for a valid repo as well.

            Please note that this was the default behaviour in older versions of GitPython,
            which is considered a bug though.
        :raise InvalidGitRepositoryError:
        :raise NoSuchPathError:
        :return: git.Repo """
        epath = _expand_path(path or os.getcwd())
        self.git = None  # should be set for __del__ not to fail in case we raise
        if not os.path.exists(epath):
            raise NoSuchPathError(epath)

        self.working_dir = None
        self._working_tree_dir = None
        self.git_dir = None
        curpath = epath

        # walk up the path to find the .git dir
        while curpath:
            # ABOUT os.path.NORMPATH
            # It's important to normalize the paths, as submodules will otherwise initialize their
            # repo instances with paths that depend on path-portions that will not exist after being
            # removed. It's just cleaner.
            if is_git_dir(curpath):
                self.git_dir = os.path.normpath(curpath)
                self._working_tree_dir = os.path.dirname(self.git_dir)
                break

            gitpath = find_git_dir(join(curpath, '.git'))
            if gitpath is not None:
                self.git_dir = os.path.normpath(gitpath)
                self._working_tree_dir = curpath
                break

            if not search_parent_directories:
                break
            curpath, dummy = os.path.split(curpath)
            if not dummy:
                break
        # END while curpath

        if self.git_dir is None:
            raise InvalidGitRepositoryError(epath)

        self._bare = False
        try:
            self._bare = self.config_reader("repository").getboolean(
                'core', 'bare')
        except Exception:
            # lets not assume the option exists, although it should
            pass

        # adjust the wd in case we are actually bare - we didn't know that
        # in the first place
        if self._bare:
            self._working_tree_dir = None
        # END working dir handling

        self.working_dir = self._working_tree_dir or self.git_dir
        self.git = self.GitCommandWrapperType(self.working_dir)

        # special handling, in special times
        args = [join(self.git_dir, 'objects')]
        if issubclass(odbt, GitCmdObjectDB):
            args.append(self.git)
        self.odb = odbt(*args)
예제 #57
0
 def _get_packed_refs_path(cls, repo):
     return join(repo.git_dir, 'packed-refs')