Completed
Push — develop ( 21434c...1a05c2 )
by Jace
11s
created

gitman/cli.py (1 issue)

1
#!/usr/bin/env python3
2
3 1
"""Command-line interface."""
4
5 1
import sys
6 1
import argparse
7 1
import logging
8
9 1
from . import CLI, VERSION, DESCRIPTION
10 1
from . import common
11 1
from . import commands
12
13 1
log = logging.getLogger(__name__)
14
15
16 1
def main(args=None, function=None):
17
    """Process command-line arguments and run the program."""
18
19
    # Shared options
20 1
    debug = argparse.ArgumentParser(add_help=False)
21 1
    debug.add_argument('-V', '--version', action='version', version=VERSION)
22 1
    group = debug.add_mutually_exclusive_group()
23 1
    group.add_argument('-v', '--verbose', action='count', default=0,
24
                       help="enable verbose logging")
25 1
    group.add_argument('-q', '--quiet', action='store_const', const=-1,
26
                       dest='verbose', help="only display errors and prompts")
27 1
    project = argparse.ArgumentParser(add_help=False)
28 1
    project.add_argument('-r', '--root', metavar='PATH',
29
                         help="root directory of the project")
30 1
    depth = argparse.ArgumentParser(add_help=False)
31 1
    depth.add_argument('-d', '--depth', type=common.positive_int,
32
                       default=5, metavar="NUM",
33
                       help="limit the number of dependency levels")
34 1
    options = argparse.ArgumentParser(add_help=False)
35 1
    options.add_argument('-f', '--force', action='store_true',
36
                         help="overwrite uncommitted changes in dependencies")
37 1
    options.add_argument('-c', '--clean', action='store_true',
38
                         help="delete ignored files in dependencies")
39 1
    shared = {'formatter_class': common.WideHelpFormatter}
40
41
    # Main parser
42 1
    parser = argparse.ArgumentParser(prog=CLI, description=DESCRIPTION,
43
                                     parents=[debug], **shared)
44 1
    subs = parser.add_subparsers(help="", dest='command', metavar="<command>")
45
46
    # Install parser
47 1
    info = "get the specified versions of all dependencies"
48 1
    sub = subs.add_parser('install', description=info.capitalize() + '.',
49
                          help=info, parents=[debug, project, depth, options],
50
                          **shared)
51 1
    sub.add_argument('name', nargs='*',
52
                     help="list of dependencies names to install")
53 1
    sub.add_argument('-e', '--fetch', action='store_true',
54
                     help="always fetch the latest branches")
55
56
    # Update parser
57 1
    info = "update dependencies to the latest versions"
58 1
    sub = subs.add_parser('update', description=info.capitalize() + '.',
59
                          help=info, parents=[debug, project, depth, options],
60
                          **shared)
61 1
    sub.add_argument('name', nargs='*',
62
                     help="list of dependencies names to update")
63 1
    sub.add_argument('-a', '--all', action='store_true', dest='recurse',
64
                     help="update all nested dependencies, recursively")
65 1
    group = sub.add_mutually_exclusive_group()
66 1
    group.add_argument('-l', '--lock',
67
                       action='store_true', dest='lock', default=None,
68
                       help="enable recording of versions for later reinstall")
69 1
    group.add_argument('-L', '--no-lock',
70
                       action='store_false', dest='lock', default=None,
71
                       help="disable recording of versions for later reinstall")
72
73
    # Display parser
74 1
    info = "display the current version of each dependency"
75 1
    sub = subs.add_parser('list', description=info.capitalize() + '.',
76
                          help=info, parents=[debug, project, depth], **shared)
77 1
    sub.add_argument('-D', '--no-dirty', action='store_false',
78
                     dest='allow_dirty',
79
                     help="fail if a source has uncommitted changes")
80
81
    # Lock parser
82 1
    info = "lock the current version of each dependency"
83 1
    sub = subs.add_parser('lock', description=info.capitalize() + '.',
84
                          help=info, parents=[debug, project], **shared)
85 1
    sub.add_argument('name', nargs='*',
86
                     help="list of dependency names to lock")
87
88
    # Uninstall parser
89 1
    info = "delete all installed dependencies"
90 1
    sub = subs.add_parser('uninstall', description=info.capitalize() + '.',
91
                          help=info, parents=[debug, project], **shared)
92 1
    sub.add_argument('-f', '--force', action='store_true',
93
                     help="delete uncommitted changes in dependencies")
94
95
    # Show parser
96 1
    info = "display the path of a dependency or internal file"
97 1
    sub = subs.add_parser('show', description=info.capitalize() + '.',
98
                          help=info, parents=[debug, project], **shared)
99 1
    sub.add_argument('name', nargs='*',
100
                     help="display the path of this dependency")
101 1
    sub.add_argument('-c', '--config', action='store_true',
102
                     help="display the path of the config file")
103 1
    sub.add_argument('-l', '--log', action='store_true',
104
                     help="display the path of the log file")
105
106
    # Edit parser
107 1
    info = "open the configuration file in the default editor"
108 1
    sub = subs.add_parser('edit', description=info.capitalize() + '.',
109
                          help=info, parents=[debug, project], **shared)
110
111
    # Parse arguments
112 1
    namespace = parser.parse_args(args=args)
113
114
    # Configure logging
115 1
    common.configure_logging(namespace.verbose)
116
117
    # Run the program
118 1
    function, args, kwargs, exit_message = _get_command(function, namespace)
119 1
    if function is None:
120 1
        parser.print_help()
121 1
        sys.exit(1)
122 1
    _run_command(function, args, kwargs, exit_message)
123
124
125 1
def _get_command(function, namespace):
0 ignored issues
show
This function should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
126 1
    args = []
127 1
    kwargs = {}
128 1
    exit_message = None
129
130 1
    if namespace.command in ['install', 'update']:
131 1
        function = getattr(commands, namespace.command)
132 1
        args = namespace.name
133 1
        kwargs.update(root=namespace.root,
134
                      depth=namespace.depth,
135
                      force=namespace.force,
136
                      clean=namespace.clean)
137 1
        if namespace.command == 'install':
138 1
            kwargs.update(fetch=namespace.fetch)
139 1
        if namespace.command == 'update':
140 1
            kwargs.update(recurse=namespace.recurse,
141
                          lock=namespace.lock)
142 1
        exit_message = "Run again with '--force' to overwrite changes"
143
144 1
    elif namespace.command == 'list':
145 1
        function = commands.display
146 1
        kwargs.update(root=namespace.root,
147
                      depth=namespace.depth,
148
                      allow_dirty=namespace.allow_dirty)
149
150 1
    elif namespace.command == 'lock':
151 1
        function = getattr(commands, namespace.command)
152 1
        args = namespace.name
153 1
        kwargs.update(root=namespace.root)
154
155 1
    elif namespace.command == 'uninstall':
156 1
        function = commands.delete
157 1
        kwargs.update(root=namespace.root,
158
                      force=namespace.force)
159 1
        exit_message = "Run again with '--force' to ignore changes"
160
161 1
    elif namespace.command == 'show':
162 1
        function = commands.show
163 1
        args = namespace.name
164 1
        kwargs.update(root=namespace.root)
165 1
        if namespace.config:
166 1
            args.append('__config__')
167 1
        if namespace.log:
168 1
            args.append('__log__')
169
170 1
    elif namespace.command == 'edit':
171 1
        function = commands.edit
172 1
        kwargs.update(root=namespace.root)
173
174 1
    return function, args, kwargs, exit_message
175
176
177 1
def _run_command(function, args, kwargs, exit_message):
178 1
    success = False
179 1
    try:
180 1
        log.debug("Running %s command...", getattr(function, '__name__', 'a'))
181 1
        success = function(*args, **kwargs)
182 1
    except KeyboardInterrupt:
183 1
        log.debug("Command canceled")
184 1
    except RuntimeError as exc:
185 1
        common.dedent(0)
186 1
        common.show(str(exc), color='error')
187 1
        common.show()
188 1
        if exit_message:
189
            common.show(exit_message, color='message')
190
            common.show()
191
192 1
    if success:
193 1
        log.debug("Command succeeded")
194
    else:
195 1
        log.debug("Command failed")
196 1
        sys.exit(1)
197
198
199
if __name__ == '__main__':  # pragma: no cover (manual test)
200
    main()
201