addet qfc not as a submodule
This commit is contained in:
parent
cc8e05e3d5
commit
bbf0120ad6
13 changed files with 806 additions and 5 deletions
114
.qfc/qfc/dirhandler.py
Normal file
114
.qfc/qfc/dirhandler.py
Normal file
|
@ -0,0 +1,114 @@
|
|||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
class CVSHandler():
|
||||
""" Handler of CVS (fir, mercurial...) directories,
|
||||
The main purpose of this class is to cache external cvs command output, and determine the appropriate files to yield when navigating to a subdirectory of a project.
|
||||
This basically means that the external command is run once (ie git ls-files), cached, and when calling get_source_files on a subdirectory of the project root (ie project-root/subdir),
|
||||
filtering from all project files of is done here.
|
||||
"""
|
||||
def __init__(self, cvs):
|
||||
self._roots_cache = {}
|
||||
self._not_tracked_cache = set()
|
||||
self.cvs = cvs
|
||||
|
||||
def _get_root_from_cache(self, directory):
|
||||
""" a directory is considered cached if it's the project root or a subdirectory of that project root.
|
||||
returns the project root dir, or None if the directory is not cached.
|
||||
"""
|
||||
if directory in self._roots_cache:
|
||||
return directory
|
||||
if os.path.dirname(directory) == directory:
|
||||
return None
|
||||
return self._get_root_from_cache(os.path.dirname(directory))
|
||||
|
||||
def get_source_files(self, directory):
|
||||
if directory in self._not_tracked_cache:
|
||||
return None
|
||||
|
||||
root_dir = self._get_root_from_cache(directory)
|
||||
if not root_dir:
|
||||
try:
|
||||
# check if it's a tracked cvs dir, if yes, get the project root and the source files
|
||||
root_dir = self.cvs._get_root(directory)
|
||||
self._roots_cache[root_dir] = self.cvs._get_tracked_files(root_dir)
|
||||
except Exception as e:
|
||||
# not a cvs tracked dir, save it to not issue that command again
|
||||
self._not_tracked_cache.add(directory)
|
||||
return None
|
||||
|
||||
files = self._roots_cache[root_dir]
|
||||
# the passed directory argument is a subdirectory of the project root
|
||||
if directory != root_dir:
|
||||
rel_dir = os.path.relpath(directory, root_dir)
|
||||
files = [f[len(rel_dir)+1:] for f in files if f.startswith(rel_dir)]
|
||||
return files
|
||||
|
||||
|
||||
class Git():
|
||||
@staticmethod
|
||||
def _get_root(directory):
|
||||
return run_command("cd %s && git rev-parse --show-toplevel" % directory).strip()
|
||||
@staticmethod
|
||||
def _get_tracked_files(directory):
|
||||
return run_command("cd %s && git ls-files && git ls-files --others --exclude-standard" % directory).strip().split('\n')
|
||||
|
||||
class Mercurial():
|
||||
@staticmethod
|
||||
def _get_root(directory):
|
||||
return run_command("cd %s && hg root" % directory).strip()
|
||||
@staticmethod
|
||||
def _get_tracked_files(directory):
|
||||
return run_command("cd %s && (hg status -marcu | cut -d' ' -f2)" % directory).strip().split('\n')
|
||||
|
||||
class DefaultDirHandler():
|
||||
""" The default directory handler uses the 'find' external program to return all the files inside a given directory up to MAX_depth depth (ie, if maxdepth=2, returns all files inside that dir, and all files in a subdir of that directory)"""
|
||||
|
||||
def __init__(self):
|
||||
self._cache = {}
|
||||
self.MAX_DEPTH = 3
|
||||
|
||||
def _walk_down(self, start_dir):
|
||||
try:
|
||||
out = run_command("find %s -maxdepth %s -type f -not -path '*/\.*'" % (start_dir, self.MAX_DEPTH))
|
||||
except subprocess.CalledProcessError as e:
|
||||
# Find returns a non 0 exit status if listing a directory fails (for example, permission denied), but still output all files in other dirs
|
||||
# ignore those failed directories.
|
||||
out = e.output
|
||||
if sys.version_info >= (3, 0):
|
||||
out = out.decode('utf-8')
|
||||
if not out:
|
||||
return []
|
||||
files = out.split('\n')
|
||||
return [os.path.relpath(f, start_dir) for f in files if f]
|
||||
|
||||
def get_source_files(self, start_dir):
|
||||
if not start_dir in self._cache:
|
||||
self._cache[start_dir] = self._walk_down(start_dir)
|
||||
return self._cache[start_dir]
|
||||
|
||||
def run_command(string):
|
||||
''' fork a process to execute the command string given as argument, returning the string written to STDOUT '''
|
||||
DEVNULL = open(os.devnull, 'wb')
|
||||
out = subprocess.check_output(string, stderr=DEVNULL, shell=True)
|
||||
if sys.version_info >= (3, 0):
|
||||
return out.decode('utf-8')
|
||||
return out
|
||||
|
||||
|
||||
git = CVSHandler(Git)
|
||||
hg = CVSHandler(Mercurial)
|
||||
default = DefaultDirHandler()
|
||||
|
||||
def get_source_files(directory):
|
||||
""" check first if the given directory is inside a git tracked project, if no, check with mercurial, if no, fallback to the default handler """
|
||||
files = git.get_source_files(directory)
|
||||
# if the returned files list is empty, it's considered not a tracked directory
|
||||
if files:
|
||||
return files
|
||||
files = hg.get_source_files(directory)
|
||||
if files:
|
||||
return files
|
||||
return default.get_source_files(directory)
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue