Esempio n. 1
0
 def test__with_suffix__startswith_path_reg(self):
     # e.g. '.*/py_venv.xml'. should return has suffix (True)
     with_suffix = ExPath('py_venv.xml')
     assert with_suffix.has_file_suffix() is True
     for reg in path_regexes():
         val = ExPath(f'{reg}{with_suffix}')
         actual = val.has_file_suffix()
         assert actual is True
Esempio n. 2
0
 def test__no_suffix__endswith_path_reg(self):
     # e.g. 'py_venv.*/'. should return no suffix (False)
     no_suffix = ExPath('py_venv')
     assert no_suffix.has_file_suffix() is False
     for reg in path_regexes():
         val = ExPath(f'{no_suffix}{reg}')
         actual = val.has_file_suffix()
         assert actual is False
Esempio n. 3
0
 def test__no_suffix__surrounded_by_path_reg(self):
     # e.g. '.*/py_venv.*/'. should return no suffix (False)
     no_suffix = ExPath('py_venv')
     assert no_suffix.has_file_suffix() is False
     for reg in path_regexes():
         for morereg in path_regexes():
             val = ExPath(f'{morereg}{no_suffix}{reg}')
             actual = val.has_file_suffix()
             assert actual is False
Esempio n. 4
0
 def test__doesnt_exist__0(self):
     bad = ExPath('/uzer/*')
     assert not bad.exists()
     assert not bad.is_dir()
     assert not bad.is_file()
     
     bad2 = ExPath('/*DOESNTEXIST')
     assert not bad2.exists()
     assert not bad2.is_dir()
     assert not bad2.is_file()
Esempio n. 5
0
 def values(self) -> List[ExPath]:
     with self.file.open(mode='r') as file:
         data = file.read()
     lines = data.splitlines()
     paths = []
     for x in lines:
         if not bool(x) or '#' in x or not WORD_RE.search(x):
             continue
         paths.append(ExPath(x))
     return [*paths, ExPath('.git')]
Esempio n. 6
0
def test____eq__():
    gilad = ExPath(giladdirstr)
    for path in path_ctor_permutations(giladdirstr):
        assert gilad == path
    for path in path_ctor_permutations('~/'):
        assert gilad == path
    gilad = ExPath('~/')
    for path in path_ctor_permutations('~/'):
        assert gilad == path
    for path in path_ctor_permutations(giladdirstr):
        assert gilad == path
Esempio n. 7
0
 def test__everything_mixed_with_regex(self):
     # e.g. '.*/py_v[en]*v.xm?l'. should return has suffix (True)
     assert ExPath('.*/py_v[en]*v.xm?l').has_file_suffix() is True
     mixed_stems = get_permutations_in_size_range(f'{REGEX_CHAR}.py_venv-1257', slice(5), has_letters_and_punc)
     for stem in mixed_stems:
         for suffix in mixed_suffixes():
             name = ExPath(f'{stem}.{suffix}')
             actual = name.has_file_suffix()
             assert actual is True
             for reg in path_regexes():
                 val = ExPath(f'{reg}{name}')
                 actual = val.has_file_suffix()
                 assert actual is True
Esempio n. 8
0
    def search(self, keyword: Union[str, ExPath], *, noprompt=True) -> ExPath:
        """Tries to return an ExPath in status.
         First assumes `keyword` is an exact file (str or ExPath), and if fails, uses `search` module.
         @param noprompt: specify False to allow using search_and_prompt(keyword, file) in case nothing matched earlier.
         """
        darkprint(f'Status.search({repr(keyword)}) |')
        path = ExPath(keyword)
        for file in self.files:
            if file == path:
                return file
        has_suffix = path.has_file_suffix()
        has_slash = '/' in keyword
        has_regex = regex.has_regex(keyword)
        darkprint(f'\t{has_suffix = }, {has_slash = }, {has_regex = }')
        if has_suffix:
            files = self.files
        else:
            files = [f.with_suffix('') for f in self.files]

        if has_regex:
            for expath in files:
                if re.search(keyword, str(expath)):
                    return expath
        if has_slash:
            darkprint(
                f"looking for the nearest match among status paths for: '{keyword}'"
            )
            return ExPath(search.nearest(keyword, files))
        darkprint(
            f"looking for a matching part among status paths ({'with' if has_suffix else 'without'} suffixes...) for: '{keyword}'"
        )
        for f in files:
            # TODO: integrate into git.search somehow
            for i, part in enumerate(f.parts):
                if part == keyword:
                    ret = ExPath(os.path.join(*f.parts[0:i + 1]))
                    return ret
        if noprompt:
            return None
        darkprint(
            f"didn't find a matching part, calling search_and_prompt()...")
        choice = search_and_prompt(keyword, [str(f) for f in files],
                                   criterion='substring')
        if choice:
            return ExPath(choice)

        prompt.generic(colors.red(f"'{keyword}' didn't match anything"),
                       flowopts=True)
Esempio n. 9
0
 def test__usr__1(self):
     # because '/usr/*' is parent of '/usr/local',
     # '/usr/' isn't parent of '/usr/*'
     # (because they function the same)
     usr_wc = ExPath('/usr/')
     for path in path_ctor_permutations('/usr/*'):
         assert not usr_wc.parent_of(path)
Esempio n. 10
0
 def is_subpath_of_ignored(self, p) -> bool:
     """Returns True if `p` is strictly a subpath of a path in .gitignore"""
     path = ExPath(p)
     for ignored in self:
         if ignored.parent_of(path):
             return True
     return False
Esempio n. 11
0
def handle_exclude_paths(
        exclude_paths_str: str) -> Tuple[ExPath, List[ExPath]]:
    """Does the '.config/dconf copyq' trick"""
    if not exclude_paths_str:
        return None, None
    if '/' in exclude_paths_str:
        exclude_parent, _, exclude_paths = exclude_paths_str.rpartition('/')
        exclude_parent = ExPath(exclude_parent)
        exclude_paths = [
            exclude_parent / ExPath(ex) for ex in exclude_paths.split(' ')
        ]
    else:
        raise NotImplementedError(
            f'only currently handled format is `.ipython/profile_default/startup ipython_config.py`'
        )
    return exclude_parent, exclude_paths
Esempio n. 12
0
 def test__single_wildcard__part_of_part(self):
     assert ExPath('/home/gilad/.bashr*').is_file()
     assert ExPath('/home/gil*d').is_dir()
     assert ExPath('/home/gil*d').is_file() is False
     assert ExPath('/*ome/gilad').is_dir()
     assert ExPath('/*ome/gilad').is_file() is False
     assert ExPath('/home/gil*d/.bashrc').is_dir() is False
     assert ExPath('/home/gil*d/.bashrc').is_file()
     assert ExPath('/*ome/gilad/.bashrc').is_file()
Esempio n. 13
0
 def test__parent_is_actually_file(self):
     # both really exist but a file isn't a parent of anything
     file = ExPath('/home/gilad/.local/bin/pip*')
     for otherfile in path_ctor_permutations('/home/gilad/.local/bin/pip3'):
         try:
             assert not file.parent_of(otherfile)
         except AssertionError as e:
             misc.brightredprint(f'file: {repr(file)} ({type(file)}) is not parent of otherfile: {repr(otherfile)} ({type(otherfile)})')
             raise
Esempio n. 14
0
def build_paths(exclude_parent, exclude_paths, ignore_paths) -> List[ExPath]:
    logger.debug(f'exclude_parent:', exclude_parent, 'exclude_paths:',
                 exclude_paths, 'ignore_paths:', ignore_paths)
    statusfiles = None
    paths: List[ExPath] = []
    skip_non_existent = False
    ignore_non_existent = False
    for f in ignore_paths:
        # * wildcard
        if "*" in f:
            paths.append(f)  # TODO: now that ExPath supports glob, ...
            continue

        # * index
        try:
            if not statusfiles:
                statusfiles = Status().files
            f = statusfiles[int(str(f))]
        except IndexError:
            i = input(
                f'Index error with {f} (len of files: {len(statusfiles)}), try again:\t'
            )
            f = statusfiles[int(i)]
        except ValueError:
            pass  # not a number

        path = ExPath(f)

        if not path.exists():
            if skip_non_existent:
                continue
            if not ignore_non_existent:
                key, choice = prompt.action(f'{path} does not exist',
                                            'skip',
                                            'ignore anyway',
                                            sA='skip all',
                                            iA='ignore all')
                if key == 'skip':
                    continue
                if key == 'sA':
                    skip_non_existent = True
                elif key == 'iA':
                    ignore_non_existent = True

                continue

        if path == exclude_parent:
            # path: '.config', exclude_paths: ['.config/dconf']
            for sub in filter(lambda p: p not in exclude_paths,
                              path.iterdir()):
                paths.append(sub)
        else:
            paths.append(path)
    if not paths:
        sys.exit(colors.brightred(f'no paths in {ExPath(".").absolute()}'))
    return paths
Esempio n. 15
0
 def is_ignored(self, p) -> bool:
     """Returns True if `p` in .gitignore, or if `p` is a subpath of a path in .gitignore,
     or if `p` fullmatches any part of a path in .gitignore (i.e. if 'env' is ignored, then 'src/env' returns True)"""
     path = ExPath(p)
     for ignored in self:
         if ignored == path:
             return True
         if ignored.parent_of(path):
             return True
         if any(re.fullmatch('env', part) for part in path.parts):
             return True
     return False
Esempio n. 16
0
 def unignore(self, path, *, confirm=False, dry_run=False, backup=True):
     path = ExPath(path)
     newvals = []
     found = False
     for ignored in self:
         if ignored == path:
             breakpoint()
             found = True
             continue
         newvals.append(ignored)
     if not found:
         logging.warning(f'Gitignore.unignore(path={path}): not in self. returning')
         return
     
     if confirm and not prompt.confirm(f'Remove {path} from .gitignore?'):
         print('aborting')
         return
     self.write(newvals, verify_paths=False, dry_run=dry_run, backup=backup)
Esempio n. 17
0
 def backup(self, confirm: bool):
     if confirm and not prompt.confirm(f'Backup .gitignore to .gitignore.backup?'):
         print('aborting')
         return False
     absolute = self.file.absolute()
     
     try:
         shell.run(f'cp {absolute} {absolute}.backup', raiseexc='summary')
     except Exception as e:
         if not prompt.confirm('Backup failed, overwrite .gitignore anyway?', flowopts='debug'):
             print('aborting')
             return False
         return True
     else:
         backup = ExPath(f'{absolute}.backup')
         if not backup.exists() and not prompt.confirm(f'Backup command completed without error, but {backup} doesnt exist. overwrite .gitignore anyway?', flowopts='debug'):
             print('aborting')
             return False
         return True
Esempio n. 18
0
        def _clean_shortstatus(
                _statusline: str) -> Optional[Tuple[ExPath, str]]:
            if _statusline.startswith("#"):

                return None

            _status, _file = map(misc.unquote,
                                 map(str.strip, _statusline.split(maxsplit=1)))
            if 'R' in _status:
                if '->' not in _file:
                    raise ValueError(
                        f"'R' in status but '->' not in file. file: {_file}, status: {_status}",
                        locals())
                _, _, _file = _file.partition(' -> ')  # return only existing
            else:
                if '->' in _file:
                    raise ValueError(
                        f"'R' not in status but '->' in file. file: {_file}, status: {_status}",
                        locals())
            return ExPath(_file), _status
Esempio n. 19
0
def main(commitmsg: str, dry_run: bool = False):
    status = Status()
    if not status.files:
        if prompt.confirm('No files in status, just push?'):
            if dry_run:
                misc.whiteprint('dry run, not pushing. returning')
                return
            return git.push()

    cwd = ExPath(os.getcwd())

    largefiles: Dict[ExPath, float] = get_large_files_from_status(cwd, status)
    if largefiles:
        handle_large_files(cwd, largefiles, dry_run)

    if '.zsh_history' in status:
        pwd = misc.getsecret('general')
        with open('/home/gilad/.zsh_history', errors='backslashreplace') as f:
            history = f.readlines()
            for i, line in enumerate(history):
                if pwd in line:
                    misc.redprint(
                        f"password found in .zsh_history in line {i}. exiting")
                    return

    if not commitmsg:
        if len(status.files) == 1:
            commitmsg = status.files[0]
        elif len(status.files) < 3:
            commitmsg = ', '.join([f.name for f in status.files])
        else:
            os.system('git status -s')
            commitmsg = input('commit msg:\t')
    commitmsg = misc.unquote(commitmsg)
    if dry_run:
        misc.whiteprint('dry run. exiting')
        return
    shell.run('git add .', f'git commit -am "{commitmsg}"')
    git.push()
Esempio n. 20
0
 def test__subpath_is_actually_file(self):
     file = ExPath('/home/gilad/.local/*')
     for otherfile in path_ctor_permutations('/home/gilad/.local/bin/pip3'):
         assert file.parent_of(otherfile)
Esempio n. 21
0
 def test__multiple_wildcards__whole_part(self):
     assert ExPath('/*/gilad/*').is_dir()
     assert ExPath('/*/gilad/*').is_file() is False
Esempio n. 22
0
 def test__real_world(self):
     for nosuffix in ['.*/py_venv.*/',
                      'file',
                      'home/gilad/.local/*', ]:
         assert not ExPath(nosuffix).has_file_suffix()
Esempio n. 23
0
 def test__with_mixed_regex_suffix(self):
     # e.g. 'py_venv.xm?l'. should return has suffix (True)
     for suffix in mixed_suffixes():
         with_suffix = ExPath(f'py_venv.{suffix}')
         actual = with_suffix.has_file_suffix()
         assert actual is True
Esempio n. 24
0
 def __contains__(self, item):
     path = ExPath(item)
     for ignored in self:
         if ignored == path:
             return True
     return False
Esempio n. 25
0
 def test__single_wildcard__whole_part__0(self):
     assert ExPath('/usr/*').is_dir()
     assert ExPath('/usr/*/share').is_dir()
     assert ExPath('/*/local/share').is_dir()
     assert ExPath('/usr/*/BAD').is_dir() is False
     assert ExPath('/usr/*/shar').is_dir() is False
     assert ExPath('/usr/*/shar').is_file() is False
     assert ExPath('/usr/*/shar').exists() is False
     assert ExPath('/*/local/shar').is_dir() is False
     assert ExPath('/*/local/shar').is_file() is False
     assert ExPath('/*/local/shar').exists() is False
     assert ExPath('/home/gilad/*').is_dir()
     assert ExPath('/home/gilad/*').is_file() is False
     assert ExPath('/home/*/.bashrc').is_dir() is False
     assert ExPath('/home/*/.bashrc').is_file()
     assert ExPath('/*/gilad/.bashrc').is_file()
Esempio n. 26
0
 def __init__(self):
     self.file = ExPath('.gitignore')
     if not self.file.exists():
         raise FileNotFoundError(f'Gitignore.__init__(): {self.file.absolute()} does not exist')
Esempio n. 27
0
 def test__single_wildcard__whole_part__1(self):
     assert ExPath('/*/gilad').is_dir()
     assert ExPath('/*/gilad').is_file() is False
Esempio n. 28
0
 def test__subpath_not_exists__0(self):
     usr_wc_share = ExPath('/usr/*/share')
     for path in path_ctor_permutations('/usr/local/share/bad'):
         assert not usr_wc_share.parent_of(path)
Esempio n. 29
0
 def test__multiple_wildcards__part_of_part(self):
     assert ExPath('/home/*/.b*shrc').is_dir() is False
     assert ExPath('/home/*/.b*shrc').is_file()
     assert ExPath('/*ome/*/.b*shrc').is_dir() is False
     assert ExPath('/*ome/*/.b*shrc').is_file()
     assert ExPath('/*/*/.b*shrc').is_file()
     assert ExPath('/*/*/.b*shrc').is_dir() is False
     assert ExPath('/home/gil*d/.b*shrc').is_dir() is False
     assert ExPath('/home/gil*d/.b*shrc').is_file()
     assert ExPath('/home/gil*d/*').is_file() is False
     assert ExPath('/home/gil*d/*').is_dir()
     assert ExPath('/*/gil*d/*').is_dir()
     assert ExPath('/*/gil*d/*').is_file() is False
Esempio n. 30
0
 def test__mixed_dirs_and_files__multiple_wildcards(self):
     # assumes .yarn/ and .yarnrc exist
     yarn = ExPath('/home/*/.yarn*')
     assert yarn.exists()
     assert not yarn.is_dir()
     assert not yarn.is_file()