/
argparser.py
99 lines (78 loc) · 3.21 KB
/
argparser.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
"""Parse command line arguments to webdiff."""
import argparse
import os
import re
import dirdiff
import githubdiff
import github_fetcher
from localfilediff import LocalFileDiff
class UsageError(Exception):
pass
USAGE = (
'''Usage: webdiff <left_dir> <right_dir>
webdiff <left_file> <right_file>
webdiff https://github.com/<owner>/<repo>/pull/<num>
Or run "git webdiff" from a git repository.
''')
# e.g. https://github.com/danvk/dygraphs/pull/292
PULL_REQUEST_RE = re.compile(r'http[s]://(?:www.)?github.com\/([^/]+)/([^/]+)/pull/([0-9]+)(?:/.*)?')
PULL_REQUEST_NUM_RE = re.compile(r'^#([0-9]+)$')
def parse(args, version=None):
"""Returns {port, dirs: [], files: [], pr: {owner, repo, number}}."""
parser = argparse.ArgumentParser(description='Run webdiff.', usage=USAGE)
parser.add_argument('--version', action='version', version='webdiff %s' % version)
parser.add_argument('--port', '-p', type=int, help="Port to run webdiff on.", default=-1)
parser.add_argument('dirs', type=str, nargs='+',
help="Directories to diff, or a github pull request URL.")
args = parser.parse_args(args=args)
out = {}
if args.port != -1:
out['port'] = args.port
if len(args.dirs) > 2:
raise UsageError('You must specify two files/dirs (got %d)' % len(args.dirs))
if len(args.dirs) == 1:
# must be a github pull request URL
owner, repo, num = None, None, None
m = re.match(PULL_REQUEST_RE, args.dirs[0])
if m:
owner, repo, num = m.groups()
# Or perhaps something simpler like '#292'?
m = re.match(PULL_REQUEST_NUM_RE, args.dirs[0])
if m:
num = int(m.group(1))
owner, repo, num = github_fetcher.get_pr_repo(num)
if not owner:
raise UsageError('You must either specify two files, two '
'directories or a github pull request URL/#number')
out['github'] = {'owner': owner, 'repo': repo, 'num': int(num)}
else:
a, b = args.dirs
for x in (a, b):
if not os.path.exists(x):
raise UsageError('"%s" does not exist' % x)
a_dir = os.path.isdir(a)
b_dir = os.path.isdir(b)
if a_dir and not b_dir:
raise UsageError('"%s" is a directory but "%s" is not' % (a, b))
if not a_dir and b_dir:
raise UsageError('"%s" is a directory but "%s" is not' % (b, a))
if a_dir and b_dir:
out['dirs'] = (a, b)
else:
out['files'] = (a, b)
return out
# TODO: move into dirdiff?
def _shim_for_file_diff(a_file, b_file):
'''Sets A_DIR, B_DIR and DIFF to do a one-file diff.'''
return LocalFileDiff(os.path.dirname(a_file), a_file,
os.path.dirname(b_file), b_file,
False) # probably not a move
def diff_for_args(args):
'''Returns a list of Diff objects for parsed command line args.'''
if 'dirs' in args:
return dirdiff.diff(*args['dirs'])
if 'files' in args:
return [_shim_for_file_diff(*args['files'])]
if 'github' in args:
gh = args['github']
return githubdiff.fetch_pull_request(gh['owner'], gh['repo'], gh['num'])