From af77d1d02891533476ccb57d07b45fe1697a86f5 Mon Sep 17 00:00:00 2001 From: Jon Bernard Date: Fri, 24 Jan 2020 14:48:18 -0500 Subject: WIP --- dotfiles/cli.py | 3 +++ dotfiles/dotfile.py | 14 +++++++++++++- dotfiles/exceptions.py | 5 +++++ dotfiles/repository.py | 28 +++++++++++++++++++++++----- 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/dotfiles/cli.py b/dotfiles/cli.py index c58b40f..2748d51 100644 --- a/dotfiles/cli.py +++ b/dotfiles/cli.py @@ -25,6 +25,7 @@ def confirm(method, files, repo): """ if files: # user has specified specific files, so we are not assuming all + # FIXME: this may be a directory that requires expansion return files # no files provided, so we assume all files after confirmation message = 'Are you sure you want to %s all dotfiles?' % method @@ -84,6 +85,8 @@ def cli(ctx, repos): ctx.obj = Repositories(repos) except FileNotFoundError as e: raise click.ClickException('Directory not found: %s' % e) + except DotfileException as e: + raise click.ClickException(e) @cli.command() diff --git a/dotfiles/dotfile.py b/dotfiles/dotfile.py index d81e585..64bfabb 100644 --- a/dotfiles/dotfile.py +++ b/dotfiles/dotfile.py @@ -31,6 +31,16 @@ class Dotfile(object): def __repr__(self): return '' % self.name + def __hash__(self): + return hash((self.name, self.target)) + + def __eq__(self, othr): + return ((self.name, self.target) == + (othr.name, othr.target)) + + def __lt__(self, othr): + return self.name < othr.name + def _ensure_dirs(self, debug): """Ensure the directories for both name and target are in place. @@ -145,9 +155,11 @@ class Dotfile(object): if copy: raise NotImplementedError() if self.name.exists(): - raise Exists(self.name) + # nothing to do + return if not self.target.exists(): raise TargetMissing(self.name) + import pdb; pdb.set_trace() self._ensure_dirs(debug) self._link(debug, home) diff --git a/dotfiles/exceptions.py b/dotfiles/exceptions.py index cb6021c..7f9b5c6 100644 --- a/dotfiles/exceptions.py +++ b/dotfiles/exceptions.py @@ -8,6 +8,11 @@ class DotfileException(Exception): return 'ERROR: %s' % self.message +class RepositoryNotFound(DotfileException): + def __init__(self, path): + DotfileException.__init__(self, path, 'repository not found') + + class IsDirectory(DotfileException): def __init__(self, path): DotfileException.__init__(self, path, 'is a directory') diff --git a/dotfiles/repository.py b/dotfiles/repository.py index 8d118cf..c231a55 100644 --- a/dotfiles/repository.py +++ b/dotfiles/repository.py @@ -6,6 +6,7 @@ from fnmatch import fnmatch from operator import attrgetter from .dotfile import Dotfile +from .exceptions import RepositoryNotFound from .exceptions import DotfileException, TargetIgnored from .exceptions import NotRootedInHome, InRepository, IsDirectory @@ -26,6 +27,7 @@ class Repositories(object): class Repository(object): """A repository is a directory that contains dotfiles.""" + CREATE_REPOSITORY = False REMOVE_LEADING_DOT = True IGNORE_PATTERNS = ['.git/*', '.gitignore', 'README*', '*~'] @@ -34,8 +36,11 @@ class Repository(object): self.home = Path(home).expanduser().resolve() if not self.path.exists(): - echo('Creating new repository: %s' % self.path) - self.path.mkdir(parents=True, exist_ok=True) + if self.CREATE_REPOSITORY: + self.path.mkdir(parents=True, exist_ok=True) + echo('Created new repository: %s' % self.path) + else: + raise RepositoryNotFound(self.path) if not self.home.exists(): raise FileNotFoundError(self.home) @@ -83,6 +88,7 @@ class Repository(object): if not fnmatch(str(path), '%s/*' % self.home): raise NotRootedInHome(path) if fnmatch(str(path), '%s/*' % self.path): + print('oh no') raise InRepository(path) if self._ignore(target): raise TargetIgnored(path) @@ -98,12 +104,15 @@ class Repository(object): return [x for x in dir.rglob('*') if not skip(x)] - def contents(self): + def contents(self, subdir=None): """Return dotfile objects for each file in the repository.""" def construct(target): return Dotfile(self._dotfile_path(target), target) - contents = self._contents(self.path) + path = subdir if subdir else self.path + path.relative_to(self.path) + + contents = self._contents(path) return sorted(map(construct, contents), key=attrgetter('name')) def dotfiles(self, paths): @@ -116,9 +125,14 @@ class Repository(object): dotfiles is returned to the caller. """ paths = [Path(x).expanduser().absolute() for x in paths] + dotfiles = [] + + # if dir doesn't exist, this breaks + # need to get entire list and compare each one as a subset for path in paths: if path.is_dir(): + dotfiles.extend(self.contents(self._dotfile_target(path))) paths.extend(self._contents(path)) paths.remove(path) @@ -129,7 +143,11 @@ class Repository(object): echo(err) return None - return [d for d in map(construct, paths) if d is not None] + # return [d for d in map(construct, paths) if d is not None] + + dotfiles.extend([d for d in map(construct, paths) if d]) + return sorted(set(dotfiles)) + def prune(self, debug=False): """Remove any empty directories in the repository. -- cgit v1.2.3