@@ -2,6 +2,8 @@ | |||||
*.egg | *.egg | ||||
*.egg-info | *.egg-info | ||||
.DS_Store | .DS_Store | ||||
__pycache__ | |||||
build | |||||
dist | |||||
Pipfile.lock | |||||
__pycache__/ | |||||
.pytest_cache/ | |||||
build/ | |||||
dist/ |
@@ -1,3 +1,10 @@ | |||||
v0.5.1 (released September 20, 2019): | |||||
- Support simple comments in the bookmarks file. (#51) | |||||
- Add an integrated pytest testing suite, runnable with `--selftest`. | |||||
- Refactor internals, remove deprecated options, and drop support for | |||||
end-of-life Python versions. | |||||
v0.5 (released August 28, 2018): | v0.5 (released August 28, 2018): | ||||
- Added a `--depth` flag to control recursion depth when searching for | - Added a `--depth` flag to control recursion depth when searching for | ||||
@@ -1,4 +1,4 @@ | |||||
Copyright (C) 2011-2018 Ben Kurtovic <ben.kurtovic@gmail.com> | |||||
Copyright (C) 2011-2019 Ben Kurtovic <ben.kurtovic@gmail.com> | |||||
Permission is hereby granted, free of charge, to any person obtaining a copy | Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
of this software and associated documentation files (the "Software"), to deal | of this software and associated documentation files (the "Software"), to deal | ||||
@@ -0,0 +1,23 @@ | |||||
[[source]] | |||||
url = "https://pypi.org/simple" | |||||
verify_ssl = true | |||||
name = "pypi" | |||||
[dev-packages] | |||||
pylint = "*" | |||||
pytest = "*" | |||||
twine = "*" | |||||
[packages] | |||||
"e1839a8" = {path = ".", editable = true} | |||||
GitPython = ">= 2.1.8" | |||||
colorama = ">= 0.3.9" | |||||
[requires] | |||||
python_version = "3.7" | |||||
[scripts] | |||||
test = "pytest gitup -v -rxw" | |||||
lint = "pylint --disable=missing-docstring --output-format=colorized gitup" | |||||
cloc = "cloc --vcs=git" | |||||
build = "python setup.py sdist bdist_wheel --universal" |
@@ -5,11 +5,15 @@ enough to handle several remotes, dirty working directories, diverged local | |||||
branches, detached HEADs, and more. It was originally created to manage a large | branches, detached HEADs, and more. It was originally created to manage a large | ||||
collection of projects and deal with sporadic internet access. | collection of projects and deal with sporadic internet access. | ||||
gitup should work on OS X, Linux, and Windows. You should have the latest | |||||
gitup should work on macOS, Linux, and Windows. You should have the latest | |||||
version of git and either Python 2.7 or Python 3 installed. | version of git and either Python 2.7 or Python 3 installed. | ||||
# Installation | # Installation | ||||
With [pip](https://github.com/pypa/pip/): | |||||
pip install gitup | |||||
With [Homebrew](http://brew.sh/): | With [Homebrew](http://brew.sh/): | ||||
brew install gitup | brew install gitup | ||||
@@ -1,6 +1,6 @@ | |||||
# -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||
# | # | ||||
# Copyright (C) 2011-2018 Ben Kurtovic <ben.kurtovic@gmail.com> | |||||
# Copyright (C) 2011-2019 Ben Kurtovic <ben.kurtovic@gmail.com> | |||||
# Released under the terms of the MIT License. See LICENSE for details. | # Released under the terms of the MIT License. See LICENSE for details. | ||||
""" | """ | ||||
@@ -8,7 +8,7 @@ gitup: the git repository updater | |||||
""" | """ | ||||
__author__ = "Ben Kurtovic" | __author__ = "Ben Kurtovic" | ||||
__copyright__ = "Copyright (C) 2011-2018 Ben Kurtovic" | |||||
__copyright__ = "Copyright (C) 2011-2019 Ben Kurtovic" | |||||
__license__ = "MIT License" | __license__ = "MIT License" | ||||
__version__ = "0.5" | |||||
__version__ = "0.5.1" | |||||
__email__ = "ben.kurtovic@gmail.com" | __email__ = "ben.kurtovic@gmail.com" |
@@ -3,7 +3,7 @@ | |||||
# Copyright (C) 2011-2018 Ben Kurtovic <ben.kurtovic@gmail.com> | # Copyright (C) 2011-2018 Ben Kurtovic <ben.kurtovic@gmail.com> | ||||
# Released under the terms of the MIT License. See LICENSE for details. | # Released under the terms of the MIT License. See LICENSE for details. | ||||
from .script import run | |||||
from gitup.cli import run | |||||
if __name__ == "__main__": | if __name__ == "__main__": | ||||
run() | run() |
@@ -10,12 +10,12 @@ import os | |||||
import platform | import platform | ||||
import sys | import sys | ||||
from colorama import init as color_init, Fore, Style | |||||
from colorama import init as color_init, Style | |||||
from . import __version__ | |||||
from .config import (get_default_config_path, get_bookmarks, add_bookmarks, | |||||
delete_bookmarks, list_bookmarks, clean_bookmarks) | |||||
from .update import update_bookmarks, update_directories, run_command | |||||
from gitup import __version__ | |||||
from gitup.config import (get_default_config_path, get_bookmarks, add_bookmarks, | |||||
delete_bookmarks, list_bookmarks, clean_bookmarks) | |||||
from gitup.update import update_bookmarks, update_directories, run_command | |||||
def _decode(path): | def _decode(path): | ||||
"""Decode the given string using the system's filesystem encoding.""" | """Decode the given string using the system's filesystem encoding.""" | ||||
@@ -23,8 +23,8 @@ def _decode(path): | |||||
return path | return path | ||||
return path.decode(sys.getfilesystemencoding()) | return path.decode(sys.getfilesystemencoding()) | ||||
def main(): | |||||
"""Parse arguments and then call the appropriate function(s).""" | |||||
def _build_parser(): | |||||
"""Build and return the argument parser.""" | |||||
parser = argparse.ArgumentParser( | parser = argparse.ArgumentParser( | ||||
description="Easily update multiple git repositories at once.", | description="Easily update multiple git repositories at once.", | ||||
epilog=""" | epilog=""" | ||||
@@ -87,25 +87,29 @@ def main(): | |||||
'-v', '--version', action="version", | '-v', '--version', action="version", | ||||
version="gitup {0} (Python {1})".format( | version="gitup {0} (Python {1})".format( | ||||
__version__, platform.python_version())) | __version__, platform.python_version())) | ||||
group_m.add_argument( | |||||
'--selftest', action="store_true", | |||||
help="run integrated test suite and exit (pytest must be available)") | |||||
# TODO: deprecated arguments, for removal in v1.0: | |||||
parser.add_argument( | |||||
'-m', '--merge', action="store_true", help=argparse.SUPPRESS) | |||||
parser.add_argument( | |||||
'-r', '--rebase', action="store_true", help=argparse.SUPPRESS) | |||||
return parser | |||||
def _selftest(): | |||||
"""Run the integrated test suite with pytest.""" | |||||
from .test import run_tests | |||||
run_tests() | |||||
def main(): | |||||
"""Parse arguments and then call the appropriate function(s).""" | |||||
parser = _build_parser() | |||||
color_init(autoreset=True) | color_init(autoreset=True) | ||||
args = parser.parse_args() | args = parser.parse_args() | ||||
print(Style.BRIGHT + "gitup" + Style.RESET_ALL + ": the git-repo-updater") | print(Style.BRIGHT + "gitup" + Style.RESET_ALL + ": the git-repo-updater") | ||||
print() | print() | ||||
# TODO: remove in v1.0 | |||||
if args.merge or args.rebase: | |||||
print(Style.BRIGHT + Fore.YELLOW + "Warning:", "--merge and --rebase " | |||||
"are deprecated. Branches are only updated if they\ntrack an " | |||||
"upstream branch and can be safely fast-forwarded. Use " | |||||
"--fetch-only to\navoid updating any branches.\n") | |||||
if args.selftest: | |||||
_selftest() | |||||
return | |||||
if args.bookmark_file: | if args.bookmark_file: | ||||
args.bookmark_file = os.path.expanduser(args.bookmark_file) | args.bookmark_file = os.path.expanduser(args.bookmark_file) |
@@ -1,6 +1,6 @@ | |||||
# -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||
# | # | ||||
# Copyright (C) 2011-2016 Ben Kurtovic <ben.kurtovic@gmail.com> | |||||
# Copyright (C) 2011-2018 Ben Kurtovic <ben.kurtovic@gmail.com> | |||||
# Released under the terms of the MIT License. See LICENSE for details. | # Released under the terms of the MIT License. See LICENSE for details. | ||||
from __future__ import print_function | from __future__ import print_function | ||||
@@ -10,7 +10,7 @@ import os | |||||
from colorama import Fore, Style | from colorama import Fore, Style | ||||
from .migrate import run_migrations | |||||
from gitup.migrate import run_migrations | |||||
__all__ = ["get_default_config_path", "get_bookmarks", "add_bookmarks", | __all__ = ["get_default_config_path", "get_bookmarks", "add_bookmarks", | ||||
"delete_bookmarks", "list_bookmarks", "clean_bookmarks"] | "delete_bookmarks", "list_bookmarks", "clean_bookmarks"] | ||||
@@ -1,6 +1,6 @@ | |||||
# -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||
# | # | ||||
# Copyright (C) 2011-2016 Ben Kurtovic <ben.kurtovic@gmail.com> | |||||
# Copyright (C) 2011-2018 Ben Kurtovic <ben.kurtovic@gmail.com> | |||||
# Released under the terms of the MIT License. See LICENSE for details. | # Released under the terms of the MIT License. See LICENSE for details. | ||||
import os | import os | ||||
@@ -0,0 +1,10 @@ | |||||
# -*- coding: utf-8 -*- | |||||
# | |||||
# Copyright (C) 2011-2018 Ben Kurtovic <ben.kurtovic@gmail.com> | |||||
# Released under the terms of the MIT License. See LICENSE for details. | |||||
def run_tests(args=None): | |||||
import pytest | |||||
if args is None: | |||||
args = ["-v", "-rxw"] | |||||
return pytest.main(args) |
@@ -0,0 +1,14 @@ | |||||
# -*- coding: utf-8 -*- | |||||
# | |||||
# Copyright (C) 2011-2018 Ben Kurtovic <ben.kurtovic@gmail.com> | |||||
# Released under the terms of the MIT License. See LICENSE for details. | |||||
from __future__ import print_function, unicode_literals | |||||
from gitup import config | |||||
def test_empty_list(tmpdir, capsys): | |||||
config_path = tmpdir / "config" | |||||
config.list_bookmarks(config_path) | |||||
captured = capsys.readouterr() | |||||
assert captured.out == "You have no bookmarks to display.\n" |
@@ -0,0 +1,24 @@ | |||||
# -*- coding: utf-8 -*- | |||||
# | |||||
# Copyright (C) 2011-2018 Ben Kurtovic <ben.kurtovic@gmail.com> | |||||
# Released under the terms of the MIT License. See LICENSE for details. | |||||
from __future__ import print_function, unicode_literals | |||||
import platform | |||||
import subprocess | |||||
import sys | |||||
from gitup import __version__ | |||||
def run_cli(*args): | |||||
cmd = [sys.executable, "-m", "gitup"] + list(args) | |||||
output = subprocess.check_output(cmd) | |||||
return output.strip().decode("utf8") | |||||
def test_cli_version(): | |||||
"""make sure we're using the right version of gitup""" | |||||
output = run_cli("-v") | |||||
expected = "gitup {} (Python {})".format( | |||||
__version__, platform.python_version()) | |||||
assert output == expected |
@@ -21,6 +21,7 @@ BOLD = Style.BRIGHT | |||||
BLUE = Fore.BLUE + BOLD | BLUE = Fore.BLUE + BOLD | ||||
GREEN = Fore.GREEN + BOLD | GREEN = Fore.GREEN + BOLD | ||||
RED = Fore.RED + BOLD | RED = Fore.RED + BOLD | ||||
CYAN = Fore.CYAN + BOLD | |||||
YELLOW = Fore.YELLOW + BOLD | YELLOW = Fore.YELLOW + BOLD | ||||
RESET = Style.RESET_ALL | RESET = Style.RESET_ALL | ||||
@@ -256,6 +257,11 @@ def _dispatch(base_path, callback, args): | |||||
Repo(base) | Repo(base) | ||||
valid = [base] | valid = [base] | ||||
except exc.NoSuchPathError: | except exc.NoSuchPathError: | ||||
if is_comment(base): | |||||
comment = get_comment(base) | |||||
if comment: | |||||
print(CYAN + BOLD + comment) | |||||
return | |||||
paths = glob(base) | paths = glob(base) | ||||
if not paths: | if not paths: | ||||
print(ERROR, BOLD + base, "doesn't exist!") | print(ERROR, BOLD + base, "doesn't exist!") | ||||
@@ -276,6 +282,14 @@ def _dispatch(base_path, callback, args): | |||||
for name, path in sorted(paths): | for name, path in sorted(paths): | ||||
callback(Repo(path), name, args) | callback(Repo(path), name, args) | ||||
def is_comment(path): | |||||
"""Does the line start with a # symbol?""" | |||||
return path.lstrip().startswith("#") | |||||
def get_comment(path): | |||||
"""Return the string minus the comment symbol.""" | |||||
return path.lstrip().lstrip("#").strip() | |||||
def update_bookmarks(bookmarks, args): | def update_bookmarks(bookmarks, args): | ||||
"""Loop through and update all bookmarks.""" | """Loop through and update all bookmarks.""" | ||||
if not bookmarks: | if not bookmarks: | ||||
@@ -18,13 +18,14 @@ with open('README.md') as fp: | |||||
setup( | setup( | ||||
name = "gitup", | name = "gitup", | ||||
packages = find_packages(), | packages = find_packages(), | ||||
entry_points = {"console_scripts": ["gitup = gitup.script:run"]}, | |||||
entry_points = {"console_scripts": ["gitup = gitup.cli:run"]}, | |||||
install_requires = ["GitPython >= 2.1.8", "colorama >= 0.3.9"], | install_requires = ["GitPython >= 2.1.8", "colorama >= 0.3.9"], | ||||
version = __version__, | version = __version__, | ||||
author = "Ben Kurtovic", | author = "Ben Kurtovic", | ||||
author_email = "ben.kurtovic@gmail.com", | author_email = "ben.kurtovic@gmail.com", | ||||
description = "Easily update multiple git repositories at once", | description = "Easily update multiple git repositories at once", | ||||
long_description = long_desc, | long_description = long_desc, | ||||
long_description_content_type = "text/markdown", | |||||
license = "MIT License", | license = "MIT License", | ||||
keywords = "git repository pull update", | keywords = "git repository pull update", | ||||
url = "https://github.com/earwig/git-repo-updater", | url = "https://github.com/earwig/git-repo-updater", | ||||
@@ -40,8 +41,6 @@ setup( | |||||
"Programming Language :: Python", | "Programming Language :: Python", | ||||
"Programming Language :: Python :: 2.7", | "Programming Language :: Python :: 2.7", | ||||
"Programming Language :: Python :: 3", | "Programming Language :: Python :: 3", | ||||
"Programming Language :: Python :: 3.2", | |||||
"Programming Language :: Python :: 3.3", | |||||
"Programming Language :: Python :: 3.4", | "Programming Language :: Python :: 3.4", | ||||
"Programming Language :: Python :: 3.5", | "Programming Language :: Python :: 3.5", | ||||
"Programming Language :: Python :: 3.6", | "Programming Language :: Python :: 3.6", | ||||