Example #1
0
    def status(self, path=None):
        """Return status of repository or file.

		Without file argument: returns status of the repository:

		:First column: working directory status (D: dirty / space)
		:Second column: index status (I: index dirty / space)
		:Third column: presence of untracked files (U: untracked files / space)
		:None: repository clean

		With file argument: returns status of this file. Output is
		equivalent to the first two columns of ``git status --porcelain``
		(except for merge statuses as they are not supported by libgit2).
		"""
        if path:
            gitd = git_directory(self.directory)
            # We need HEAD as without it using fugitive to commit causes the
            # current file’s status (and only the current file) to not be updated
            # for some reason I cannot be bothered to figure out.
            return get_file_status(
                directory=self.directory,
                dirstate_file=join(gitd, "index"),
                file_path=path,
                ignore_file_name=".gitignore",
                get_func=self.do_status,
                create_watcher=self.create_watcher,
                extra_ignore_files=tuple(join(gitd, x) for x in ("logs/HEAD", "info/exclude")),
            )
        return self.do_status(self.directory, path)
Example #2
0
    def status(self, path=None):
        '''Return status of repository or file.

		Without file argument: returns status of the repository:

		:First column: working directory status (D: dirty / space)
		:Second column: index status (I: index dirty / space)
		:Third column: presence of untracked files (U: untracked files / space)
		:None: repository clean

		With file argument: returns status of this file. Output is
		equivalent to the first two columns of ``git status --porcelain``
		(except for merge statuses as they are not supported by libgit2).
		'''
        if path:
            gitd = git_directory(self.directory)
            # We need HEAD as without it using fugitive to commit causes the
            # current file’s status (and only the current file) to not be updated
            # for some reason I cannot be bothered to figure out.
            return get_file_status(
                directory=self.directory,
                dirstate_file=join(gitd, 'index'),
                file_path=path,
                ignore_file_name='.gitignore',
                get_func=self.do_status,
                create_watcher=self.create_watcher,
                extra_ignore_files=tuple(
                    join(gitd, x) for x in ('logs/HEAD', 'info/exclude')),
            )
        return self.do_status(self.directory, path)
Example #3
0
def get_config_paths():
    """Get configuration paths from environment variables.

	Uses $XDG_CONFIG_HOME and $XDG_CONFIG_DIRS according to the XDG specification.

	:return: list of paths
	"""
    config_home = os.environ.get("XDG_CONFIG_HOME", os.path.join(os.path.expanduser("~"), ".config"))
    config_path = join(config_home, "powerline")
    config_paths = [config_path]
    config_dirs = os.environ.get("XDG_CONFIG_DIRS", DEFAULT_SYSTEM_CONFIG_DIR)
    if config_dirs is not None:
        config_paths[:0] = reversed([join(d, "powerline") for d in config_dirs.split(":")])
    plugin_path = join(os.path.realpath(os.path.dirname(__file__)), "config_files")
    config_paths.insert(0, plugin_path)
    return config_paths
Example #4
0
def get_file_status(directory, dirstate_file, file_path, ignore_file_name, get_func, create_watcher, extra_ignore_files=()):
	global file_status_cache
	keypath = file_path if os.path.isabs(file_path) else join(directory, file_path)
	file_status_cache.update_maps(keypath, directory, dirstate_file, ignore_file_name, extra_ignore_files)

	with file_status_lock:
		# Optimize case of keypath not being cached
		if keypath not in file_status_cache:
			file_status_cache[keypath] = ans = get_func(directory, file_path)
			return ans

		# Check if any relevant files have changed
		file_changed = file_watcher(create_watcher)
		changed = False
		# Check if dirstate has changed
		try:
			changed = file_changed(dirstate_file)
		except OSError as e:
			if getattr(e, 'errno', None) != errno.ENOENT:
				raise
			# The .git index file does not exist for a new git repo
			return get_func(directory, file_path)

		if changed:
			# Remove all cached values for files that depend on this
			# dirstate_file
			file_status_cache.invalidate(dirstate_file=dirstate_file)
		else:
			# Check if the file itself has changed
			try:
				changed ^= file_changed(keypath)
			except OSError as e:
				if getattr(e, 'errno', None) != errno.ENOENT:
					raise
				# Do not call get_func again for a non-existant file
				if keypath not in file_status_cache:
					file_status_cache[keypath] = get_func(directory, file_path)
				return file_status_cache[keypath]

			if changed:
				file_status_cache.pop(keypath, None)
			else:
				# Check if one of the ignore files has changed
				for ignf in file_status_cache.ignore_files(keypath):
					try:
						changed ^= file_changed(ignf)
					except OSError as e:
						if getattr(e, 'errno', None) != errno.ENOENT:
							raise
					if changed:
						# Invalidate cache for all files that might be affected
						# by this ignore file
						file_status_cache.invalidate(ignore_file=ignf)
						break

		try:
			return file_status_cache[keypath]
		except KeyError:
			file_status_cache[keypath] = ans = get_func(directory, file_path)
			return ans
Example #5
0
def get_config_paths():
	'''Get configuration paths from environment variables.

	Uses $XDG_CONFIG_HOME and $XDG_CONFIG_DIRS according to the XDG specification.

	:return: list of paths
	'''
	config_home = os.environ.get('XDG_CONFIG_HOME', os.path.join(os.path.expanduser('~'), '.config'))
	config_path = join(config_home, 'powerline')
	config_paths = [config_path]
	config_dirs = os.environ.get('XDG_CONFIG_DIRS', DEFAULT_SYSTEM_CONFIG_DIR)
	if config_dirs is not None:
		config_paths[:0] = reversed([join(d, 'powerline') for d in config_dirs.split(':')])
	plugin_path = join(os.path.realpath(os.path.dirname(__file__)), 'config_files')
	config_paths.insert(0, plugin_path)
	return config_paths
Example #6
0
 def branch(self):
     config_file = join(self.directory, '.hg', 'branch')
     return get_branch_name(
         directory=self.directory,
         config_file=config_file,
         get_func=branch_name_from_config_file,
         create_watcher=self.create_watcher,
     )
Example #7
0
	def branch(self):
		config_file = join(self.directory, '.hg', 'branch')
		return get_branch_name(
			directory=self.directory,
			config_file=config_file,
			get_func=branch_name_from_config_file,
			create_watcher=self.create_watcher,
		)
Example #8
0
 def branch(self):
     directory = git_directory(self.directory)
     head = join(directory, "HEAD")
     return get_branch_name(
         directory=directory,
         config_file=head,
         get_func=branch_name_from_config_file,
         create_watcher=self.create_watcher,
     )
Example #9
0
 def branch(self):
     directory = git_directory(self.directory)
     head = join(directory, 'HEAD')
     return get_branch_name(
         directory=directory,
         config_file=head,
         get_func=branch_name_from_config_file,
         create_watcher=self.create_watcher,
     )
Example #10
0
def _find_config_files(search_paths, config_file, config_loader=None, loader_callback=None):
    config_file += ".json"
    found = False
    for path in search_paths:
        config_file_path = join(path, config_file)
        if os.path.isfile(config_file_path):
            yield config_file_path
            found = True
        elif config_loader:
            config_loader.register_missing(_config_loader_condition, loader_callback, config_file_path)
    if not found:
        raise IOError("Config file not found in search paths ({0}): {1}".format(", ".join(search_paths), config_file))
Example #11
0
def find_all_ext_config_files(search_paths, subdir):
    for config_root in search_paths:
        top_config_subpath = join(config_root, subdir)
        if not os.path.isdir(top_config_subpath):
            if os.path.exists(top_config_subpath):
                yield {
                    'error':
                    'Path {0} is not a directory'.format(top_config_subpath),
                    'path':
                    top_config_subpath,
                }
            continue
        for ext_name in os.listdir(top_config_subpath):
            ext_path = os.path.join(top_config_subpath, ext_name)
            if not os.path.isdir(ext_path):
                if ext_name.endswith('.json') and os.path.isfile(ext_path):
                    yield updated_with_config({
                        'error': False,
                        'path': ext_path,
                        'name': ext_name[:-5],
                        'ext': None,
                        'type': 'top_' + subdir,
                    })
                else:
                    yield {
                        'error':
                        'Path {0} is not a directory or configuration file'.
                        format(ext_path),
                        'path':
                        ext_path,
                    }
                continue
            for config_file_name in os.listdir(ext_path):
                config_file_path = os.path.join(ext_path, config_file_name)
                if config_file_name.endswith('.json') and os.path.isfile(
                        config_file_path):
                    yield updated_with_config({
                        'error': False,
                        'path': config_file_path,
                        'name': config_file_name[:-5],
                        'ext': ext_name,
                        'type': subdir,
                    })
                else:
                    yield {
                        'error':
                        'Path {0} is not a configuration file'.format(
                            config_file_path),
                        'path':
                        config_file_path,
                    }
Example #12
0
	def update_maps(self, keypath, directory, dirstate_file, ignore_file_name, extra_ignore_files):
		parent = keypath
		ignore_files = set()
		while parent != directory:
			nparent = os.path.dirname(keypath)
			if nparent == parent:
				break
			parent = nparent
			ignore_files.add(join(parent, ignore_file_name))
		for f in extra_ignore_files:
			ignore_files.add(f)
		self.keypath_ignore_map[keypath] = ignore_files
		for ignf in ignore_files:
			self.ignore_map[ignf].add(keypath)
		self.dirstate_map[dirstate_file].add(keypath)
Example #13
0
def _find_config_files(search_paths, config_file, config_loader=None, loader_callback=None):
	config_file += '.json'
	found = False
	for path in search_paths:
		config_file_path = join(path, config_file)
		if os.path.isfile(config_file_path):
			yield config_file_path
			found = True
		elif config_loader:
			config_loader.register_missing(_config_loader_condition, loader_callback, config_file_path)
	if not found:
		raise IOError('Config file not found in search paths ({0}): {1}'.format(
			', '.join(search_paths),
			config_file
		))
Example #14
0
 def update_maps(self, keypath, directory, dirstate_file, ignore_file_name,
                 extra_ignore_files):
     parent = keypath
     ignore_files = set()
     while parent != directory:
         nparent = os.path.dirname(keypath)
         if nparent == parent:
             break
         parent = nparent
         ignore_files.add(join(parent, ignore_file_name))
     for f in extra_ignore_files:
         ignore_files.add(f)
     self.keypath_ignore_map[keypath] = ignore_files
     for ignf in ignore_files:
         self.ignore_map[ignf].add(keypath)
     self.dirstate_map[dirstate_file].add(keypath)
Example #15
0
def git_directory(directory):
    path = join(directory, ".git")
    if os.path.isfile(path):
        with open(path, "rb") as f:
            raw = f.read()
            if not raw.startswith(b"gitdir: "):
                raise IOError("invalid gitfile format")
            raw = raw[8:]
            if raw[-1:] == b"\n":
                raw = raw[:-1]
            if not isinstance(path, bytes):
                raw = raw.decode(get_preferred_file_name_encoding())
            if not raw:
                raise IOError("no path in gitfile")
            return os.path.abspath(os.path.join(directory, raw))
    else:
        return path
Example #16
0
def git_directory(directory):
	path = join(directory, '.git')
	if os.path.isfile(path):
		with open(path, 'rb') as f:
			raw = f.read()
			if not raw.startswith(b'gitdir: '):
				raise IOError('invalid gitfile format')
			raw = raw[8:]
			if raw[-1:] == b'\n':
				raw = raw[:-1]
			if not isinstance(path, bytes):
				raw = raw.decode(get_preferred_file_name_encoding())
			if not raw:
				raise IOError('no path in gitfile')
			return os.path.abspath(os.path.join(directory, raw))
	else:
		return path
Example #17
0
def git_directory(directory):
    path = join(directory, '.git')
    if os.path.isfile(path):
        with open(path, 'rb') as f:
            raw = f.read()
            if not raw.startswith(b'gitdir: '):
                raise IOError('invalid gitfile format')
            raw = raw[8:]
            if raw[-1:] == b'\n':
                raw = raw[:-1]
            if not isinstance(path, bytes):
                raw = raw.decode(get_preferred_file_name_encoding())
            if not raw:
                raise IOError('no path in gitfile')
            return os.path.abspath(os.path.join(directory, raw))
    else:
        return path
Example #18
0
def find_all_ext_config_files(search_paths, subdir):
	for config_root in search_paths:
		top_config_subpath = join(config_root, subdir)
		if not os.path.isdir(top_config_subpath):
			if os.path.exists(top_config_subpath):
				yield {
					'error': 'Path {0} is not a directory'.format(top_config_subpath),
					'path': top_config_subpath,
				}
			continue
		for ext_name in os.listdir(top_config_subpath):
			ext_path = os.path.join(top_config_subpath, ext_name)
			if not os.path.isdir(ext_path):
				if ext_name.endswith('.json') and os.path.isfile(ext_path):
					yield updated_with_config({
						'error': False,
						'path': ext_path,
						'name': ext_name[:-5],
						'ext': None,
						'type': 'top_' + subdir,
					})
				else:
					yield {
						'error': 'Path {0} is not a directory or configuration file'.format(ext_path),
						'path': ext_path,
					}
				continue
			for config_file_name in os.listdir(ext_path):
				config_file_path = os.path.join(ext_path, config_file_name)
				if config_file_name.endswith('.json') and os.path.isfile(config_file_path):
					yield updated_with_config({
						'error': False,
						'path': config_file_path,
						'name': config_file_name[:-5],
						'ext': ext_name,
						'type': subdir,
					})
				else:
					yield {
						'error': 'Path {0} is not a configuration file'.format(config_file_path),
						'path': config_file_path,
					}
Example #19
0
	def status(self, path=None):
		'''Return status of repository or file.

		Without file argument: returns status of the repository:

		:'D?': dirty (tracked modified files: added, removed, deleted, modified),
		:'?U': untracked-dirty (added, but not tracked files)
		:None: clean (status is empty)

		With file argument: returns status of this file: The status codes are
		those returned by bzr status -S
		'''
		if path is not None:
			return get_file_status(
				directory=self.directory,
				dirstate_file=join(self.directory, '.bzr', 'checkout', 'dirstate'),
				file_path=path,
				ignore_file_name='.bzrignore',
				get_func=self.do_status,
				create_watcher=self.create_watcher,
			)
		return self.do_status(self.directory, path)
Example #20
0
    def status_string(self, path=None):
        '''Return status of repository or file.

		Without file argument: returns status of the repository:

		:'D?': dirty (tracked modified files: added, removed, deleted, modified),
		:'?U': untracked-dirty (added, but not tracked files)
		:None: clean (status is empty)

		With file argument: returns status of this file: The status codes are
		those returned by bzr status -S
		'''
        if path is not None:
            return get_file_status(
                directory=self.directory,
                dirstate_file=join(self.directory, '.bzr', 'checkout',
                                   'dirstate'),
                file_path=path,
                ignore_file_name='.bzrignore',
                get_func=self.do_status,
                create_watcher=self.create_watcher,
            )
        return self.do_status(self.directory, path)
Example #21
0
	def status(self, path=None):
		'''Return status of repository or file.

		Without file argument: returns status of the repository:

		:'D?': dirty (tracked modified files: added, removed, deleted, modified),
		:'?U': untracked-dirty (added, but not tracked files)
		:None: clean (status is empty)

		With file argument: returns status of this file: `M`odified, `A`dded,
		`R`emoved, `D`eleted (removed from filesystem, but still tracked),
		`U`nknown, `I`gnored, (None)Clean.
		'''
		if path:
			return get_file_status(
				directory=self.directory,
				dirstate_file=join(self.directory, '.hg', 'dirstate'),
				file_path=path,
				ignore_file_name='.hgignore',
				get_func=self.do_status,
				create_watcher=self.create_watcher,
			)
		return self.do_status(self.directory, path)
Example #22
0
    def status_string(self, path=None):
        '''Return status of repository or file.

        Without file argument: returns status of the repository:

        :'D?': dirty (tracked modified files: added, removed, deleted, modified),
        :'?U': untracked-dirty (added, but not tracked files)
        :None: clean (status is empty)

        With file argument: returns status of this file: `M`odified, `A`dded,
        `R`emoved, `D`eleted (removed from filesystem, but still tracked),
        `U`nknown, `I`gnored, (None)Clean.
        '''
        if path:
            return get_file_status(
                directory=self.directory,
                dirstate_file=join(self.directory, '.hg', 'dirstate'),
                file_path=path,
                ignore_file_name='.hgignore',
                get_func=self.do_status,
                create_watcher=self.create_watcher,
            )
        return self.do_status(self.directory, path)
Example #23
0
def get_file_status(directory,
                    dirstate_file,
                    file_path,
                    ignore_file_name,
                    get_func,
                    create_watcher,
                    extra_ignore_files=()):
    global file_status_cache
    keypath = file_path if os.path.isabs(file_path) else join(
        directory, file_path)
    file_status_cache.update_maps(keypath, directory, dirstate_file,
                                  ignore_file_name, extra_ignore_files)

    with file_status_lock:
        # Optimize case of keypath not being cached
        if keypath not in file_status_cache:
            file_status_cache[keypath] = ans = get_func(directory, file_path)
            return ans

        # Check if any relevant files have changed
        file_changed = file_watcher(create_watcher)
        changed = False
        # Check if dirstate has changed
        try:
            changed = file_changed(dirstate_file)
        except OSError as e:
            if getattr(e, 'errno', None) != errno.ENOENT:
                raise
            # The .git index file does not exist for a new git repo
            return get_func(directory, file_path)

        if changed:
            # Remove all cached values for files that depend on this
            # dirstate_file
            file_status_cache.invalidate(dirstate_file=dirstate_file)
        else:
            # Check if the file itself has changed
            try:
                changed ^= file_changed(keypath)
            except OSError as e:
                if getattr(e, 'errno', None) != errno.ENOENT:
                    raise
                # Do not call get_func again for a non-existant file
                if keypath not in file_status_cache:
                    file_status_cache[keypath] = get_func(directory, file_path)
                return file_status_cache[keypath]

            if changed:
                file_status_cache.pop(keypath, None)
            else:
                # Check if one of the ignore files has changed
                for ignf in file_status_cache.ignore_files(keypath):
                    try:
                        changed ^= file_changed(ignf)
                    except OSError as e:
                        if getattr(e, 'errno', None) != errno.ENOENT:
                            raise
                    if changed:
                        # Invalidate cache for all files that might be affected
                        # by this ignore file
                        file_status_cache.invalidate(ignore_file=ignf)
                        break

        try:
            return file_status_cache[keypath]
        except KeyError:
            file_status_cache[keypath] = ans = get_func(directory, file_path)
            return ans