Exemplo n.º 1
0
    def set_flow_opts(self, flowopts: Union[str, Iterable, bool]) -> NoReturn:
        """Sets `self.flowopts` with FlowItem objects.
        Handles passing different types of flowopts (single string, tuple of strings, or boolean), and returns a FlowItem tuple."""
        darkprint(
            f'{self.__class__.__qualname__}.set_flow_opts(flowopts={repr(flowopts)})'
        )
        if flowopts is True:
            flowitems = tuple(map(FlowItem, Flow.__members__.values()))
        elif isinstance(flowopts, str):  # 'quit'
            # flowopts = (FlowItem.from_full_name(flowopts),)
            flowitems = (FlowItem(flowopts), )
        else:
            # flowopts = tuple(map(FlowItem.from_full_name, flowopts))
            flowitems = tuple(map(FlowItem, flowopts))
            if has_duplicates(flowitems):
                raise ValueError(
                    f"{repr(self)}\nset_flow_opts(flowopts) | duplicate flowitems: {repr(flowitems)}"
                )

        for flowitem in flowitems:
            self.items.store(flowitem)
            # if flowopt.value in self.items:
            #     raise ValueError(f'{repr(self)}\nset_special_options() | flowopt.value ({repr(flowopt.value)}) already exists in self.\nflowopt: {repr(flowopt)}.\nflowopts: {repr(flowopts)}')
            # self.items[flowopt.value] = flowopt.name
        return None
Exemplo n.º 2
0
def main(ignore_paths: List[ExPathOrStr],
         exclude_paths_tuple: Tuple[str, ...],
         confirm: bool = False,
         dry_run: bool = False,
         backup: bool = True):
    # TODO: support i.e. "e/h/package" for "efficient-frontier/home-task/package-lock.json"
    darkprint(
        f'ignore.py main() | ignore_paths: {ignore_paths}, exclude_paths_tuple: {exclude_paths_tuple}, confirm: {confirm}, dry_run: {dry_run}, backup: {backup}'
    )
    if exclude_paths_tuple:
        for exclude_paths_str in exclude_paths_tuple:
            ignore(confirm, dry_run, backup, ignore_paths, exclude_paths_str)
    else:
        ignore(confirm, dry_run, backup, ignore_paths)
Exemplo n.º 3
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)
Exemplo n.º 4
0
def compare(a, b):
    darkprint(f'compare({repr(a)}, {repr(b)})')
    if a == b:
        sys.exit(colors.red(f'trying to compare a branch to itself: {a}'))
    if a not in btree:
        yellowprint(f'"{a}" not in branches, searching...')
        a = btree.search(a)
    if b not in btree:
        yellowprint(f'"{b}" not in branches, searching...')
        b = btree.search(b)

    repo = Repo()
    if repo.host == 'bitbucket':
        url = f"https://{repo.weburl}/branches/compare/{a}%0D{b}#diff"
    else:
        url = f"https://{repo.weburl}/compare/{a}..{b}"
    webbrowser.open(url)
Exemplo n.º 5
0
def main(a, b):
    darkprint(f'main(a: {a}, b: {b})')
    if a and b:
        darkprint(f'comparing a to b')
        return compare(a, b)
    if a:
        darkprint(f'comparing btree.current to a')
        return compare(btree.current, a)

    # not a and not b
    darkprint(f'comparing btree.current to master')
    return compare(btree.current, 'master')
Exemplo n.º 6
0
def mutate_identifier(identifier: str):
    upper = identifier.upper()
    identifier = upper
    darkprint(
        f'mutate_identifier({repr(identifier)}) yielding upper: {repr(upper)}')
    yield upper
    words = self.val.split(' ')
    if len(words) == 1:
        raise NotImplementedError(
            f"no word separators, and both lowercase and uppercase identifier is taken ('{upper.lower()}')"
        )
    words_identifiers = ''.join(map(lambda s: s[0], words))
    identifier = words_identifiers
    darkprint(
        f'mutate_identifier() yielding words_identifiers: {repr(words_identifiers)}'
    )
    yield words_identifiers
    for i in range(len(words_identifiers)):
        new_identifiers = words_identifiers[:i] + words_identifiers[i].upper(
        ) + words_identifiers[i + 1:]
        identifier = new_identifiers
        darkprint(
            f'mutate_identifier() yielding new_identifiers (#{i}): {repr(new_identifiers)}'
        )
        yield new_identifiers
    raise StopIteration(
        f'mutate_identifier() exhausted all options: {repr(self)}')
Exemplo n.º 7
0
    def set_kw_options(self, **kw_opts: Union[str, tuple, bool]) -> None:
        """foo='bar', baz='continue'"""
        darkprint(
            f'{self.__class__.__qualname__}.set_kw_options(kw_opts={repr(kw_opts)})'
        )
        if not kw_opts:
            return
        if has_duplicates(kw_opts.values()):
            raise ValueError(
                f"{repr(self)}\nset_kw_options() duplicate kw_opts: {repr(kw_opts)}"
            )
        if 'free_input' in kw_opts:
            raise DeveloperError(
                f"{repr(self)}\nset_kw_options() | 'free_input' found in kw_opts, should have popped it out earlier.\nkw_opts: {repr(kw_opts)}"
            )
        non_flow_kw_opts = dict()
        for kw in kw_opts:
            opt = kw_opts[kw]
            if kw in self.items:
                raise ValueError(
                    f"{repr(self)}\nset_kw_options() | '{kw}' in kw_opts but was already in self.items.\nkw_opts: {repr(kw_opts)}"
                )

            try:
                # flowitem = FlowItem.from_full_name(opt)
                flowitem = FlowItem(opt)
            except ValueError:
                non_flow_kw_opts[kw] = opt
            else:
                # not using self.items.store(flowitem) because kw isn't flowitem.identifier
                self.items[kw] = flowitem

        if not non_flow_kw_opts:
            return

        kw_items = KeywordItems(non_flow_kw_opts)

        self.items.update(**kw_items)
Exemplo n.º 8
0
 def __init__(self, question: str, **kwargs):
     # noinspection PyTypeChecker
     self.answer: Answer = None
     if 'flowopts' in kwargs:
         self.options.set_flow_opts(kwargs.pop('flowopts'))
     try:
         free_input = kwargs.pop('free_input')
     except KeyError:
         free_input = False
     
     # *  keyword-choices
     self.options.set_kw_options(**kwargs)
     
     # *  Complex Prompt
     dialog_string = self.dialog_string(question, free_input=free_input)
     # question = self.dialog_string(question, options, free_input=free_input)
     key, answer = self.get_answer(dialog_string, free_input=free_input)
     darkprint(f'{repr(self)} | key: {repr(key)}, answer: {repr(answer)}')
     # *  FlowItem Answer
     if isinstance(answer, FlowItem):
         # flow_answer: FlowItem = FlowItem(answer)
         answer.execute()
         
         if answer.DEBUG:
             # debugger had already started and had finished in answer.execute() (user 'continue'd here)
             self.answer = self.get_answer(dialog_string)
         elif answer.CONTINUE:
             self.answer: Tuple[str, FlowItem] = key, answer
         else:
             raise NotImplementedError
     else:
         # *  DIDN'T answer any flow
         
         if isinstance(answer, MutableItem) and answer.is_yes_or_no:
             darkprint(f'{repr(self)} no flow chosen, answer is yes / no. key: {repr(key)}, answer: {repr(answer)}, options: {self.options}')
             self.answer: bool = key.lower() in ('y', 'yes')
         else:
             darkprint(f'{repr(self)} no flow chosen, answer is not yes / no. key: {repr(key)}, answer: {repr(answer)}, options: {self.options}')
             self.answer: Tuple[str, MutableItem] = key, answer
Exemplo n.º 9
0
def main(items: Tuple[str], exclude):
    # TODO: option to view in web like comparebranch
    exclude_exts = []
    if exclude:
        for ex in map(misc.clean, exclude.split(' ')):
            exclude_exts.append(misc.quote(f':!{ex}'))

    cmd = 'git diff --color-moved=zebra --find-copies-harder --ignore-blank-lines --ignore-cr-at-eol --ignore-space-at-eol --ignore-space-change --ignore-all-space '
    darkprint(f'diff.py main(items): {items}')
    if not items:
        # TODO: exclude
        shell.run(cmd, stdout=sys.stdout)

    btree = Branches()
    ctree = Commits()
    formatted = []
    # if exclude_exts:

    gitignore = None
    status = Status()

    any_sha = False
    diff_files = set()

    for i, item in enumerate(map(misc.clean, items)):
        if regex.SHA_RE.fullmatch(item):
            # e.g. 'f5905f1'
            any_sha = True
            if i > 1:
                redprint(
                    f'SHA1 items, if any, must be placed at the most in the first 2 arg slots'
                )
                return
            if item in ctree:
                if i == 1 and formatted[0] not in ctree:
                    redprint(
                        f'When specifying two SHA1 args, both must belong to the same tree. 0th arg doesnt belong to ctree, 1st does'
                    )
                    return
                formatted.append(item)
                continue
            if item in btree:
                if i == 1 and formatted[0] not in btree:
                    redprint(
                        f'When specifying two SHA1 args, both must belong to the same tree. 0th arg doesnt belong to btree, 1st does'
                    )
                    return
                formatted.append(item)
                continue
            redprint(
                f'item is SHA1 but not in commits nor branches. item: {repr(item)}'
            )
            return
        else:
            if any_sha:
                # all SHA items have already been appended, and current item is not a SHA
                numstat_cmd = f'git diff --numstat {" ".join(items[:i])}'
            else:
                # no SHA items at all, this is the first item
                numstat_cmd = f'git diff --numstat'
            filestats = shell.runquiet(numstat_cmd).splitlines()
            diff_files = set(line.rpartition('	')[2] for line in filestats)

        # TODO (continue here):
        #  gpdy SHA SHA REGEX -e REGEX
        #  make -e filter out results

        if item in diff_files:
            with_quotes = misc.quote(item)
            formatted.append(with_quotes)
            darkprint(f'appended: {with_quotes}')
        else:
            brightwhiteprint(
                f'{item} is not in diff_files, searching within diff_files...')
            choice = search_and_prompt(item, diff_files)
            if choice:
                with_quotes = misc.quote(choice)
                formatted.append(with_quotes)
                darkprint(f'appended: {with_quotes}')

        # file = status.search(item, quiet=False)
        # if not file:
        #     brightyellowprint(f'{item} is not in status, skipping')
        #     continue
        # stripped = misc.unquote(file.strip())
        # formatted.append(misc.quote(stripped))
        # darkprint(f'appended: {repr(stripped)}')

    joined = " ".join(formatted)
    cmd += f'{joined} '
    if exclude_exts:
        cmd += " ".join(exclude_exts)

    shell.run(cmd, stdout=sys.stdout)
Exemplo n.º 10
0
 def is_yes_or_no(self):
     ret = bool(YES_OR_NO.fullmatch(self.identifier))
     darkprint(f'{repr(self)}.is_yes_or_no() → {ret}')
     return ret