Show NoUpstream error in checkup output.
This commit is contained in:
		
							parent
							
								
									e557c1a64f
								
							
						
					
					
						commit
						015957f72d
					
				
					 1 changed files with 63 additions and 61 deletions
				
			
		| 
						 | 
					@ -4,6 +4,7 @@ import subprocess
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
import types
 | 
					import types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from voussoirkit import dotdict
 | 
				
			||||||
from voussoirkit import winwhich
 | 
					from voussoirkit import winwhich
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GIT = winwhich.which('git')
 | 
					GIT = winwhich.which('git')
 | 
				
			||||||
| 
						 | 
					@ -17,19 +18,22 @@ GIT = winwhich.which('git')
 | 
				
			||||||
# ?? file3
 | 
					# ?? file3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class NoUpstreamBranch(Exception):
 | 
					class NoUpstreamBranch(Exception):
 | 
				
			||||||
    pass
 | 
					    def __str__(self):
 | 
				
			||||||
 | 
					        return f'No upstream branch for {self.args[0]}'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def check_output(command):
 | 
					def check_output(command):
 | 
				
			||||||
    output = subprocess.check_output(command, stderr=subprocess.STDOUT)
 | 
					    output = subprocess.check_output(command, stderr=subprocess.STDOUT)
 | 
				
			||||||
    return output
 | 
					    return output
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def checkup_committed():
 | 
					def checkup_committed():
 | 
				
			||||||
 | 
					    details = dotdict.DotDict(default=None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    command = [GIT, 'status', '--short', '--untracked-files=all']
 | 
					    command = [GIT, 'status', '--short', '--untracked-files=all']
 | 
				
			||||||
    output = check_output(command)
 | 
					    output = check_output(command)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    added = 0
 | 
					    details.added = 0
 | 
				
			||||||
    modified = 0
 | 
					    details.modified = 0
 | 
				
			||||||
    deleted = 0
 | 
					    details.deleted = 0
 | 
				
			||||||
    for line in output.splitlines():
 | 
					    for line in output.splitlines():
 | 
				
			||||||
        status = line.split()[0].strip().decode('ascii')
 | 
					        status = line.split()[0].strip().decode('ascii')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,18 +41,19 @@ def checkup_committed():
 | 
				
			||||||
        # added in the index but deleted on disk, etc. Anyway these numbers
 | 
					        # added in the index but deleted on disk, etc. Anyway these numbers
 | 
				
			||||||
        # don't need to be super accurate, just enough to remind you to commit.
 | 
					        # don't need to be super accurate, just enough to remind you to commit.
 | 
				
			||||||
        if {'A', '?'}.intersection(status):
 | 
					        if {'A', '?'}.intersection(status):
 | 
				
			||||||
            added += 1
 | 
					            details.added += 1
 | 
				
			||||||
        if {'M', 'R', '!'}.intersection(status):
 | 
					        if {'M', 'R', '!'}.intersection(status):
 | 
				
			||||||
            modified += 1
 | 
					            details.modified += 1
 | 
				
			||||||
        if {'D'}.intersection(status):
 | 
					        if {'D'}.intersection(status):
 | 
				
			||||||
            deleted += 1
 | 
					            details.deleted += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    committed = (added, modified, deleted) == (0, 0, 0)
 | 
					    details.committed = (details.added, details.modified, details.deleted) == (0, 0, 0)
 | 
				
			||||||
    details = types.SimpleNamespace(added=added, deleted=deleted, modified=modified)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (committed, details)
 | 
					    return details
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def checkup_pushed():
 | 
					def checkup_pushed():
 | 
				
			||||||
 | 
					    details = dotdict.DotDict(default=None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    command = [GIT, 'rev-parse', '@']
 | 
					    command = [GIT, 'rev-parse', '@']
 | 
				
			||||||
    my_head = check_output(command).strip().decode()
 | 
					    my_head = check_output(command).strip().decode()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,33 +63,28 @@ def checkup_pushed():
 | 
				
			||||||
    except subprocess.CalledProcessError as exc:
 | 
					    except subprocess.CalledProcessError as exc:
 | 
				
			||||||
        command = [GIT, 'rev-parse', '--abbrev-ref', 'HEAD']
 | 
					        command = [GIT, 'rev-parse', '--abbrev-ref', 'HEAD']
 | 
				
			||||||
        current_branch = check_output(command).strip().decode()
 | 
					        current_branch = check_output(command).strip().decode()
 | 
				
			||||||
        raise NoUpstreamBranch(current_branch)
 | 
					        details.error = NoUpstreamBranch(current_branch)
 | 
				
			||||||
 | 
					        return details
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if my_head == remote_head:
 | 
					    if my_head == remote_head:
 | 
				
			||||||
        to_push = 0
 | 
					        details.to_push = 0
 | 
				
			||||||
        to_pull = 0
 | 
					        details.to_pull = 0
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        command = [GIT, 'merge-base', '@', '@{u}']
 | 
					        command = [GIT, 'merge-base', '@', '@{u}']
 | 
				
			||||||
        merge_base = check_output(command)
 | 
					        merge_base = check_output(command).strip().decode()
 | 
				
			||||||
        merge_base = merge_base.strip().decode()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if my_head == merge_base:
 | 
					        if my_head == merge_base:
 | 
				
			||||||
            to_push = 0
 | 
					            details.to_push = 0
 | 
				
			||||||
            to_pull = len(git_commits_between(merge_base, remote_head))
 | 
					            details.to_pull = len(git_commits_between(merge_base, remote_head))
 | 
				
			||||||
        elif remote_head == merge_base:
 | 
					        elif remote_head == merge_base:
 | 
				
			||||||
            to_push = len(git_commits_between(merge_base, my_head))
 | 
					            details.to_push = len(git_commits_between(merge_base, my_head))
 | 
				
			||||||
            to_pull = 0
 | 
					            details.to_pull = 0
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            to_push = len(git_commits_between(merge_base, my_head))
 | 
					            details.to_push = len(git_commits_between(merge_base, my_head))
 | 
				
			||||||
            to_pull = len(git_commits_between(merge_base, remote_head))
 | 
					            details.to_pull = len(git_commits_between(merge_base, remote_head))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pushed = (to_push, to_pull) == (0, 0)
 | 
					    details.pushed = (details.to_push, details.to_pull) == (0, 0)
 | 
				
			||||||
    details = types.SimpleNamespace(
 | 
					    return details
 | 
				
			||||||
        to_push=to_push,
 | 
					 | 
				
			||||||
        to_pull=to_pull,
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return (pushed, details)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
def git_commits_between(a, b):
 | 
					def git_commits_between(a, b):
 | 
				
			||||||
    command = [GIT, 'log', '--oneline', f'{a}..{b}']
 | 
					    command = [GIT, 'log', '--oneline', f'{a}..{b}']
 | 
				
			||||||
| 
						 | 
					@ -100,12 +100,10 @@ def checkup(directory, do_fetch=False):
 | 
				
			||||||
    os.chdir(directory)
 | 
					    os.chdir(directory)
 | 
				
			||||||
    if do_fetch:
 | 
					    if do_fetch:
 | 
				
			||||||
        git_fetch()
 | 
					        git_fetch()
 | 
				
			||||||
    (committed, commit_details) = checkup_committed()
 | 
					    commit_details = checkup_committed()
 | 
				
			||||||
    (pushed, push_details) = checkup_pushed()
 | 
					    push_details = checkup_pushed()
 | 
				
			||||||
    return types.SimpleNamespace(
 | 
					    return dotdict.DotDict(
 | 
				
			||||||
        committed=committed,
 | 
					 | 
				
			||||||
        commit_details=commit_details,
 | 
					        commit_details=commit_details,
 | 
				
			||||||
        pushed=pushed,
 | 
					 | 
				
			||||||
        push_details=push_details,
 | 
					        push_details=push_details,
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -121,21 +119,14 @@ def read_directories_file():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return directories
 | 
					    return directories
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def gitcheckup(do_fetch=False):
 | 
					def gitcheckup_one(directory, do_fetch=False):
 | 
				
			||||||
    try:
 | 
					 | 
				
			||||||
        directories = read_directories_file()
 | 
					 | 
				
			||||||
    except FileNotFoundError as exc:
 | 
					 | 
				
			||||||
        print(f'Please put your git repo locations in {exc.filename}.')
 | 
					 | 
				
			||||||
        return 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for directory in directories:
 | 
					 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        result = checkup(directory, do_fetch=do_fetch)
 | 
					        result = checkup(directory, do_fetch=do_fetch)
 | 
				
			||||||
    except subprocess.CalledProcessError as exc:
 | 
					    except subprocess.CalledProcessError as exc:
 | 
				
			||||||
        raise Exception(exc.output)
 | 
					        raise Exception(exc.output)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        committed = 'C' if result.committed else ' '
 | 
					    committed = 'C' if result.commit_details.committed else ' '
 | 
				
			||||||
        pushed = 'P' if result.pushed else ' '
 | 
					    pushed = 'P' if result.push_details.pushed else ' '
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    details = []
 | 
					    details = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -149,6 +140,7 @@ def gitcheckup(do_fetch=False):
 | 
				
			||||||
    push_details = []
 | 
					    push_details = []
 | 
				
			||||||
    if result.push_details.to_push: push_details.append(f'↑{result.push_details.to_push}')
 | 
					    if result.push_details.to_push: push_details.append(f'↑{result.push_details.to_push}')
 | 
				
			||||||
    if result.push_details.to_pull: push_details.append(f'↓{result.push_details.to_pull}')
 | 
					    if result.push_details.to_pull: push_details.append(f'↓{result.push_details.to_pull}')
 | 
				
			||||||
 | 
					    if result.push_details.error: push_details.append(f'!{result.push_details.error}')
 | 
				
			||||||
    push_details = ', '.join(push_details)
 | 
					    push_details = ', '.join(push_details)
 | 
				
			||||||
    if push_details: details.append(f'({push_details})')
 | 
					    if push_details: details.append(f'({push_details})')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -156,8 +148,18 @@ def gitcheckup(do_fetch=False):
 | 
				
			||||||
    details = (' ' + details).rstrip()
 | 
					    details = (' ' + details).rstrip()
 | 
				
			||||||
    print(f'[{committed}][{pushed}] {directory}{details}')
 | 
					    print(f'[{committed}][{pushed}] {directory}{details}')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def gitcheckup_all(do_fetch=False):
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        directories = read_directories_file()
 | 
				
			||||||
 | 
					    except FileNotFoundError as exc:
 | 
				
			||||||
 | 
					        print(f'Please put your git repo locations in {exc.filename}.')
 | 
				
			||||||
 | 
					        return 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for directory in directories:
 | 
				
			||||||
 | 
					        gitcheckup_one(directory, do_fetch=do_fetch)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def gitcheckup_argparse(args):
 | 
					def gitcheckup_argparse(args):
 | 
				
			||||||
    return gitcheckup(do_fetch=args.do_fetch)
 | 
					    return gitcheckup_all(do_fetch=args.do_fetch)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def main(argv):
 | 
					def main(argv):
 | 
				
			||||||
    parser = argparse.ArgumentParser(description=__doc__)
 | 
					    parser = argparse.ArgumentParser(description=__doc__)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue