Completed
Push — develop ( d80a58...75cc86 )
by Jace
28s queued 12s
created

gitman.commands.update()   C

Complexity

Conditions 8

Size

Total Lines 70
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 33
CRAP Score 8

Importance

Changes 0
Metric Value
cc 8
eloc 43
nop 9
dl 0
loc 70
ccs 33
cts 33
cp 1
crap 8
rs 6.9813
c 0
b 0
f 0

How to fix   Long Method    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
"""Functions to manage the installation of dependencies."""
2
3 1
import datetime
4 1
import functools
5 1
import os
6 1
7
import log
8 1
9 1
from . import common, system
10
from .models import Config, Source, load_config
11 1
12
13
def restore_cwd(func):
14 1
    @functools.wraps(func)
15 1
    def wrapped(*args, **kwargs):
16
        cwd = os.getcwd()
17 1
        result = func(*args, **kwargs)
18 1
        os.chdir(cwd)
19 1
        return result
20 1
21 1
    return wrapped
22
23
24 1
def init():
25
    """Create a new config file for the project."""
26 1
    success = False
27
28 1
    config = load_config()
29
30 1
    if config:
31 1
        msg = "Configuration file already exists: {}".format(config.path)
32 1
        common.show(msg, color='error')
33
34
    else:
35 1
        config = Config()
36 1
        source = Source(
37
            type='git',
38 1
            name="sample_dependency",
39 1
            repo="https://github.com/githubtraining/hellogitworld",
40 1
        )
41 1
        config.sources.append(source)
42
        source = source.lock(rev="ebbbf773431ba07510251bb03f9525c7bab2b13a")
43 1
        config.sources_locked.append(source)
44 1
        config.datafile.save()
45 1
46
        msg = "Created sample config file: {}".format(config.path)
47 1
        common.show(msg, color='success')
48 1
        success = True
49
50 1
    msg = "To edit this config file, run: gitman edit"
51
    common.show(msg, color='message')
52
53 1
    return success
54 1
55
56
@restore_cwd
57
def install(
58
    *names,
59
    root=None,
60
    depth=None,
61
    force=False,
62
    fetch=False,
63
    force_interactive=False,
64
    clean=True,
65
    skip_changes=False,
66
):
67
    """Install dependencies for a project.
68
69 1
    Optional arguments:
70
71
    - `*names`: optional list of dependency directory names to filter on
72 1
    - `root`: specifies the path to the root working tree
73
    - `depth`: number of levels of dependencies to traverse
74 1
    - `force`: indicates uncommitted changes can be overwritten and
75
               script errors can be ignored
76 1
    - `force_interactive`: indicates uncommitted changes can be interactively
77 1
    overwritten and script errors can be ignored
78 1
    - `fetch`: indicates the latest branches should always be fetched
79 1
    - `clean`: indicates untracked files should be deleted from dependencies
80 1
    - `skip_changes`: indicates dependencies with uncommitted changes
81
     should be skipped
82
    """
83
    log.info(
84
        "%sInstalling dependencies: %s",
85 1
        'force-' if force or force_interactive else '',
86 1
        ', '.join(names) if names else '<all>',
87
    )
88 1
    count = None
89
90
    config = load_config(root)
91 1
92 1
    if config:
93
        common.newline()
94
        common.show("Installing dependencies...", color='message', log=False)
95
        common.newline()
96
        count = config.install_dependencies(
97
            *names,
98
            update=False,
99
            depth=depth,
100
            force=force,
101
            force_interactive=force_interactive,
102
            fetch=fetch,
103
            clean=clean,
104
            skip_changes=skip_changes,
105
        )
106
107
        if count:
108 1
            _run_scripts(
109
                *names, depth=depth, force=force, _config=config, show_shell_stdout=True
110
            )
111
112 1
    return _display_result("install", "Installed", count)
113
114 1
115
@restore_cwd
116 1
def update(
117 1
    *names,
118 1
    root=None,
119 1
    depth=None,
120 1
    recurse=False,
121
    force=False,
122
    force_interactive=False,
123
    clean=True,
124
    lock=None,  # pylint: disable=redefined-outer-name
125 1
    skip_changes=False,
126 1
):
127
    """Update dependencies for a project.
128 1
129 1
    Optional arguments:
130
131 1
    - `*names`: optional list of dependency directory names to filter on
132 1
    - `root`: specifies the path to the root working tree
133
    - `depth`: number of levels of dependencies to traverse
134 1
    - `recurse`: indicates nested dependencies should also be updated
135
    - `force`: indicates uncommitted changes can be overwritten and
136
               script errors can be ignored
137 1
    - `force_interactive`: indicates uncommitted changes can be interactively
138
    overwritten and script errors can be ignored
139
    - `clean`: indicates untracked files should be deleted from dependencies
140
    - `lock`: indicates updated dependency versions should be recorded
141
    - `skip_changes`: indicates dependencies with uncommitted changes
142
     should be skipped
143
    """
144
    log.info(
145
        "%s dependencies%s: %s",
146
        'Force updating' if force or force_interactive else 'Updating',
147 1
        ', recursively' if recurse else '',
148
        ', '.join(names) if names else '<all>',
149 1
    )
150 1
    count = None
151 1
152
    config = load_config(root)
153
154 1
    if config:
155 1
        common.newline()
156
        common.show("Updating dependencies...", color='message', log=False)
157
        common.newline()
158
        count = config.install_dependencies(
159
            *names,
160
            update=True,
161
            depth=depth,
162
            recurse=recurse,
163
            force=force,
164
            force_interactive=force_interactive,
165 1
            fetch=True,
166 1
            clean=clean,
167
            skip_changes=skip_changes,
168 1
        )
169
170 1
        if count and lock is not False:
171 1
            common.show("Recording installed versions...", color='message', log=False)
172 1
            common.newline()
173
            config.lock_dependencies(
174 1
                *names,
175 1
                obey_existing=lock is None,
176 1
                skip_changes=skip_changes or force_interactive,
177 1
            )
178
179 1
        if count:
180 1
            _run_scripts(
181 1
                *names, depth=depth, force=force, _config=config, show_shell_stdout=True
182
            )
183 1
184
    return _display_result("update", "Updated", count)
185
186 1
187 1
def _run_scripts(
188
    *names, depth=None, force=False, _config=None, show_shell_stdout=False
189
):
190
    """Run post-install scripts.
191
192
    Optional arguments:
193
194
    - `*names`: optional list of dependency directory names filter on
195
    - `depth`: number of levels of dependencies to traverse
196 1
    - `force`: indicates script errors can be ignored
197 1
    - `show_shell_stdout`: allows to print realtime output from shell commands
198
199 1
    """
200
    assert _config, "'_config' is required"
201 1
202 1
    common.show("Running scripts...", color='message', log=False)
203 1
    common.newline()
204 1
    _config.run_scripts(
205 1
        *names, depth=depth, force=force, show_shell_stdout=show_shell_stdout
206 1
    )
207
208 1
209
@restore_cwd
210
def display(*, root=None, depth=None, allow_dirty=True):
211 1
    """Display installed dependencies for a project.
212 1
213
    Optional arguments:
214
215
    - `root`: specifies the path to the root working tree
216
    - `depth`: number of levels of dependencies to traverse
217
    - `allow_dirty`: causes uncommitted changes to be ignored
218
219
    """
220
    log.info("Displaying dependencies...")
221 1
    count = None
222 1
223
    config = load_config(root)
224 1
225
    if config:
226 1
        common.newline()
227 1
        common.show(
228 1
            "Displaying current dependency versions...", color='message', log=False
229
        )
230 1
        common.newline()
231 1
        config.log(datetime.datetime.now().strftime("%F %T"))
232 1
        count = 0
233 1
        for identity in config.get_dependencies(depth=depth, allow_dirty=allow_dirty):
234 1
            count += 1
235 1
            config.log("{}: {} @ {}", *identity)
236
        config.log()
237 1
238
    return _display_result("display", "Displayed", count)
239
240 1
241
@restore_cwd
242
def lock(*names, root=None):
243
    """Lock current dependency versions for a project.
244
245
    Optional arguments:
246
247 1
    - `*names`: optional list of dependency directory names to filter on
248
    - `root`: specifies the path to the root working tree
249 1
250
    """
251 1
    log.info("Locking dependencies...")
252 1
    count = None
253 1
254
    config = load_config(root)
255 1
256 1
    if config:
257
        common.newline()
258 1
        common.show("Locking dependencies...", color='message', log=False)
259
        common.newline()
260
        count = config.lock_dependencies(*names, obey_existing=False)
261 1
        common.dedent(level=0)
262
263
    return _display_result("lock", "Locked", count)
264
265
266
@restore_cwd
267
def delete(*, root=None, force=False, keep_location=False):
268
    """Delete dependencies for a project.
269 1
270
    Optional arguments:
271 1
272
    - `root`: specifies the path to the root working tree
273 1
    - `force`: indicates uncommitted changes can be overwritten
274 1
    - `keep_location`: delete top level folder or keep the location
275 1
276
    """
277 1
    log.info("Deleting dependencies...")
278
    count = None
279
280 1
    config = load_config(root)
281
282
    if config:
283
        common.newline()
284
        common.show("Checking for uncommitted changes...", color='message', log=False)
285
        common.newline()
286
        count = len(list(config.get_dependencies(allow_dirty=force)))
287
        common.dedent(level=0)
288
        common.show("Deleting all dependencies...", color='message', log=False)
289
        common.newline()
290
        if keep_location:
291
            config.clean_dependencies()
292
        else:
293
            config.uninstall_dependencies()
294
295
    return _display_result("delete", "Deleted", count, allow_zero=True)
296 1
297 1
298 1
def show(*names, root=None):
299 1
    """Display the path of an installed dependency or internal file.
300
301 1
    - `name`: dependency name or internal file keyword
302
    - `root`: specifies the path to the root working tree
303 1
304 1
    """
305 1
    log.info("Finding paths...")
306 1
307
    config = load_config(root)
308 1
309 1
    if not config:
310
        log.error("No config found")
311
        return False
312
313
    for name in names or [None]:
314
        common.show(config.get_path(name), color='path')
315
316
    return True
317
318
319
def edit(*, root=None):
320
    """Open the confuration file for a project.
321
322
    Optional arguments:
323
324
    - `root`: specifies the path to the root working tree
325
326
    """
327
    log.info("Launching config...")
328
329
    config = load_config(root)
330
331
    if not config:
332
        log.error("No config found")
333
        return False
334
335
    return system.launch(config.path)
336
337
338
def _display_result(present, past, count, allow_zero=False):
339
    """Convert a command's dependency count to a return status.
340
341
    >>> _display_result("sample", "Sampled", 1)
342
    True
343
344
    >>> _display_result("sample", "Sampled", None)
345
    False
346
347
    >>> _display_result("sample", "Sampled", 0)
348
    False
349
350
    >>> _display_result("sample", "Sampled", 0, allow_zero=True)
351
    True
352
353
    """
354
    if count is None:
355
        log.warning("No dependencies to %s", present)
356
    elif count == 1:
357
        log.info("%s 1 dependency", past)
358
    else:
359
        log.info("%s %s dependencies", past, count)
360
361
    if count:
362
        return True
363
    if count is None:
364
        return False
365
366
    assert count == 0
367
    return allow_zero
368