def _get_large_files_in_dir(path: ExPath) -> Dict[ExPath, float]: large_subfiles = {} for p in path.iterdir(): if not p.exists(): misc.yellowprint( f'_get_large_files_in_dir() | does not exist: {repr(p)}') continue if p.is_file(): mb = p.size('mb') if mb >= 50: large_subfiles[p] = mb else: large_subfiles.update(_get_large_files_in_dir(p)) return large_subfiles
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)
def main(paths): print(f'main({", ".join(paths)})') # TODO: see if exists in status if not paths: sys.exit(colors.red('no values! exiting')) cmds = [] gitignore = Gitignore() status = Status() existing_paths = [] for p in paths: breakpoint() path = status.search(p, noprompt=False) if not path: yellowprint(f"status.search({p}) return None, skipping") continue if not path.exists(): yellowprint(f"{p} does not exist, skipping") continue # exists if path.is_dir(): cmds.append(f'git rm -r --cached {path}') else: cmds.append(f'git rm --cached {path}') existing_paths.append(path) if not cmds: sys.exit(colors.red('no values to rm, exiting')) shell.run(*cmds, raiseexc=False) if prompt.confirm(f'try to ignore {len(existing_paths)} values?'): gitignore.write(existing_paths) commitmsg = f'Removed from cache: ' + ', '.join(map(str, paths)) answer = prompt.generic(f'commit and push?', f'yes, commit with "{commitmsg}"', 'custom commit message', flowopts='quit') if answer is not True: commitmsg = prompt.generic('commit msg:', free_input=True)[1] shell.run(f'git commit -am "{commitmsg}"') git.push()
def get_large_files_from_status(cwd, status: Status) -> Dict[ExPath, float]: largefiles = {} for f in status.files: statuce = status.file_status_map[f] if 'D' in statuce: continue # TODO: check if already in gitignore and just not removed from cache if any(qu in str(cwd) or qu in str(f) for qu in ['"', "'"]): misc.yellowprint( f'get_large_files_from_status() | found quote in `cwd` or `f`') breakpoint() abspath = cwd / f if any(qu in str(abspath) for qu in ['"', "'"]): misc.yellowprint( f'get_large_files_from_status() | found quote in `abspath`: probably a bug in ExPath __div__' ) breakpoint() mb = 0 if abspath.exists(): if abspath.is_dir(): large_subfiles = _get_large_files_in_dir(abspath) largefiles.update(large_subfiles) else: mb = abspath.size('mb') else: misc.yellowprint( f'get_large_files_from_status() | does not exist: {repr(abspath)}' ) if mb >= 50: largefiles[abspath] = mb return largefiles
def main(branch): status = Status() if status: if not prompt.confirm('Uncommitted changes, checkout anyway?'): print('aborting') return btree = Branches() if branch not in btree: yellowprint(f'"{branch}" not in branches, searching...') branch = btree.search(branch) if btree.current == branch: yellowprint(f'Already on {branch}') return if not branch: redprint(f"Couldn't find branch") return shell.run(f'git checkout {branch}') if not prompt.confirm('git pull?'): print('aborting') return if git.pull() == 1: brightyellowprint(f"git pull failed")
def run(*cmds: str, printout=True, printcmd=True, raiseexc: RaiseArg = True, raise_on_non_zero: RaiseArg = False, input: bytes = None, stdout=sp.PIPE, stderr=sp.PIPE, **runargs): """ Basically a wrapper to `subprocess.run(shlex.split(cmd))` that returns stdout(s) strings. Always: - Prints stderr (if exists) in bright yellow. - Uses ExcHandler if an exception occurrs :param cmds: :param bool printout: Print the output of each command. Default True. :param bool printcmd: Print the command before execution in italic bright black. Default True. :param raiseexc: Regarding python exceptions, not failed commands. If False, suppresses exceptions, but prints their summaries. If True, actually raises the exception, but prints ExcHandler beforehand. Value can be a bool or either 'short', 'summary', 'full' to control the output of ExcHandler. True is equiv to 'full'. Default True. :param raise_on_non_zero: If False, completely ignores returncode. If True, and returncode != zero, raises ChildProcessError, but prints ExcHandler beforehand. Value can be a bool or either 'short', 'summary', 'full' to control the output of ExcHandler. True is equiv to 'full'. Default False. Note: stderr may have content but returncode is 0, and vice-versa. :param bytes input: Default None. :param int stdout: default sp.PIPE (-1). STDOUT is -2, DEVNULL is -3. :param int stderr: default sp.PIPE (-1). STDOUT is -2, DEVNULL is -3. :param runargs: any other kwargs `subprocess.run` might accept. 'stdout', 'stderr' and 'input' are overwritten :return: A string or a list of strings (stripped), depending on whether a single command or many commands were passed. If no command had any output, returns an empty str. Examples: :: >>> vanilla = sp.run(shlex.split('rm does/not/exist'), stderr=sp.PIPE).stderr.decode().strip() >>> run('rm does/not/exist', stderr=sp.STDOUT) == vanilla ... ... ... True """ # TODO: poll every second for long processes, like git clone outs = [] for cmd in cmds: if printcmd: print(colors.brightblack(f'\n{cmd}', "italic")) try: if isinstance(stdout, str): yellowprint( f'shell.run() stdout is str, not passing it: {misc.trim_at(stdout, 60)}' ) else: runargs['stdout'] = stdout if isinstance(stderr, str): yellowprint( f'shell.run() stderr is str, not passing it: {misc.trim_at(stderr, 60)}' ) else: runargs['stderr'] = stderr if input: runargs['input'] = input proc: sp.CompletedProcess = sp.run(shlex.split(cmd), **runargs) if proc.stdout: out = proc.stdout.decode().strip() else: out = None if proc.stderr: stderr = proc.stderr.decode().strip() brightyellowprint(stderr) # keep after stderr handling so stderr is printed before raise if raise_on_non_zero and proc.returncode != 0: _handle_exception(ChildProcessError( f"shell.run() | The following command returned with code {proc.returncode}:\n{cmd}" ), raise_on_non_zero, msg=f'returncode: {proc.returncode}') except Exception as e: _handle_exception(e, raiseexc, msg=f'FAILED: `{cmd}`\n\t{e.__class__.__name__}') else: if out: if printout: print(out, end='\n') outs.append(out) if outs: return outs[0] if len(outs) == 1 else outs return ''