Commit 1edb4eda authored by Thomas Johannesmeyer's avatar Thomas Johannesmeyer
Browse files

Merge branch 'release/0.6.0'

* release/0.6.0:
  Bump version number to 0.6.0
  Implement autostash and log improvements
parents d6903b0f 0d993497
......@@ -45,7 +45,6 @@ def main(argv):
ap.add_argument('-dir', '--directory', help='Name of the folder you would like to extract')
ap.add_argument('-t', '--tag', help='String the Tag you would like to checkout contains')
# ap.add_argument('-b', '--branch', help='String the Tag you would like to checkout contains')
ap.add_argument('-x', '--xml', help='Provide an xml config file')
......@@ -54,12 +53,12 @@ def main(argv):
# Flags
ap.add_argument('-l', '--log', default=False, action='store_true', help='Create Logfile')
ap.add_argument('-p', '--prune', default=False, action='store_true', help='Prune on pull')
ap.add_argument('-s', '--autostash', default=False, action='store_true', help='Enable autostash before checking out dirty directory')
ap.add_argument('-u', '--update', default=False, action='store_true', help='Pull from origin/master into master prior to checkout')
ap.add_argument('-v', '--verbose', default=False, action='store_true', help='Increase verbosity')
# ap.add_argument('path', nargs='?')
# path = os.path.normpath(options.path)
##
# Validate / Parse provided arguments
options = ap.parse_args()
##
......@@ -72,6 +71,7 @@ def main(argv):
xml_path = options.xml
# Flags
should_autostash = options.autostash
should_create_logfile = options.log
should_prune = options.prune
should_update = options.update
......@@ -79,12 +79,13 @@ def main(argv):
##
# Configuring tagsnag using the provided arguments
tagsnag.set_verbose(options.verbose)
tagsnag.set_verbose(verbose)
tagsnag.set_should_autostash(should_autostash)
tagsnag.set_should_prune(should_prune)
tagsnag.set_create_logfile(should_create_logfile)
if should_update:
tagsnag.update_all_repos(should_prune=should_prune)
tagsnag.update_all_repos()
if xml_path:
tagsnag.start_with_xml(xml_path)
......@@ -104,10 +105,6 @@ def main(argv):
display_help()
except KeyboardInterrupt:
tagsnag.log.info('Keyboard Interrupt detected: Exiting.')
pass
......
......@@ -9,7 +9,7 @@ with open('LICENSE', 'r') as fh:
setuptools.setup(
name = 'Tagsnatch',
version = '0.5.0',
version = '0.6.0',
author = 'Thomas Johannesmeyer',
author_email = 'opensource@geeky.gent',
description = 'Search files over multiple Git repos, and extract a certain version',
......
......@@ -49,7 +49,7 @@ class Tagsnag():
self.copy_file_to_destination(path = found_paths[0], destination = snag.destination)
def update_all_repos(self, should_prune=False):
def update_all_repos(self):
"""Initiate threaded updates for all repositories in working directory"""
if not self.repos:
......@@ -60,18 +60,34 @@ class Tagsnag():
with ThreadPoolExecutor(max_workers=max_worker_count) as executor:
for repo in self.repos:
executor.submit(self.update_repo, repo, should_prune=should_prune)
executor.submit(self.update_repo, repo)
def update_repo(self, repo, should_prune=False):
def update_repo(self, repo):
"""Update provided repository"""
repo_path = self.get_root(repo)
repo_name = os.path.basename(repo_path)
self.log.info('Initiating update for {} repository'.format(repo_name))
self.log.info('[{}]: Checking status.'.format(repo_name))
if self.is_dirty(repo):
self.log.info(' [{}]: Dirty repository detected.'.format(repo_name))
if self.should_autostash:
self.log.info(' [{}]: Autostash enabled. Stashing...'.format(repo_name))
self.stash_repo(repo)
else:
self.log.info(' [{}]: Autostash disabled. Skipping...'.format(repo_name))
return
else:
self.log.debug(' [{}]: Status clean.'.format(repo_name))
self.log.info('[{}]: Initiating update...'.format(repo_name))
self.checkout(repo, 'master')
self.pull(repo, should_prune=should_prune)
self.pull(repo)
def find_tag(self, repo, keyword):
......@@ -116,11 +132,15 @@ class Tagsnag():
repo_path = self.get_root(repo)
repo_name = os.path.basename(repo_path)
self.log.info('Searching for corresponding tag for keyword: {}'.format(tag))
self.log.info('[{}]: Searching for corresponding tag for keyword: {}'.format(repo_name, tag))
valid_tag = self.find_tag(repo, tag)
if valid_tag == '':
self.log.info('{} tag could not be found in {}. Skipping repo'.format(tag, repo_name))
self.log.info(' [{}]: {} tag could not be found. Skipping repo'.format(repo_name, tag))
return
else:
self.log.info(' [{}]: Valid Tag found: {} -> {}'.format(repo_name, tag, valid_tag))
self.checkout(repo, valid_tag)
......@@ -150,10 +170,10 @@ class Tagsnag():
repo_path = self.get_root(repo)
repo_name = os.path.basename(repo_path)
self.log.info('Searching for corresponding tag for keyword: {}'.format(tag))
self.log.info('[{}]: Searching for corresponding tag for keyword: {}'.format(repo_name, tag))
valid_tag = self.find_tag(repo, tag)
if valid_tag == '':
self.log.info('{} tag could not be found. Skipping repo'.format(tag))
self.log.info('[{}]: <{}> tag could not be found. Skipping repo'.format(repo_name, tag))
return
self.checkout(repo, valid_tag)
......@@ -190,6 +210,13 @@ class Tagsnag():
self.repo_names_and_urls = {}
self.repositories = {}
##
# Flags
self.should_prune = False
self.should_autostash = False
self.verbose = False
self.should_create_logfile = False
# Advanced setup
self.setup_logger()
......@@ -293,16 +320,20 @@ class Tagsnag():
def checkout(self, repo, target):
""" Checkout provided target within given repository """
self.log.debug('Checking out {} in {}'.format(target, self.get_root(repo)))
git = repo.git
git.checkout(target)
def pull(self, repo, should_prune=False):
def pull(self, repo):
""" Pull origin / master for provided repository """
self.log.debug('Pulling origin/master {}'.format(self.get_root(repo)))
git = repo.git
if should_prune:
if self.should_prune:
git.pull('origin', 'master')
git.pull('origin', '--tags')
......@@ -311,6 +342,30 @@ class Tagsnag():
git.pull('origin', '--tags', '--prune')
def is_dirty(self, repo):
""" Returns True if repository status is dirty """
diff_result = repo.index.diff(None)
if len(diff_result) > 0:
return True
else:
return False
def stash_repo(self, repo):
""" Run stash within provided repository """
git = repo.git
git.stash()
def stash_pop_repo(self, repo):
""" Run stash within provided repository """
git = repo.git
git.stash('pop')
def get_root(self, repo):
return repo.git.rev_parse("--show-toplevel")
......@@ -342,19 +397,18 @@ class Tagsnag():
repo_path = os.path.normpath("{}/{}".format(destination_path, repo_name))
self.log.debug(repo_path)
if os.path.exists(repo_path):
self.log.info('Repository {} exists.'.format(repo_name))
self.log.info('[{}]: Repository exists.'.format(repo_name))
repo = Repo(repo_path)
assert not repo.bare
self.repositories[repo_name] = repo
else:
self.log.info('Repository {} does not exist. Attempting to clone it...'.format(repo_name))
self.log.info('[{}]: Repository does not exist. Attempting to clone it...'.format(repo_name))
# @todo: Implement
# self.clone_repository(destination=repo_path, url=url)
def search_directory(self, directory, path='.'):
normalized_dirname = directory.lower()
found_paths = []
......@@ -427,6 +481,8 @@ class Tagsnag():
# Helper methods
def is_git_dir(self, path):
""" Returns True if path contains valid Git repo """
try:
Repo(path)
return True
......@@ -434,6 +490,13 @@ class Tagsnag():
return False
def get_repo_name(self, repo):
""" Returns name of provided repo """
repo_path = self.get_root(repo)
repo_name = os.path.basename(repo_path)
def available_cpu_count(self):
""" Number of available virtual or physical CPUs on this system, i.e.
user/real as output by time(1) when called with an optimally scaling
......@@ -560,7 +623,20 @@ class Tagsnag():
logging.getLogger().setLevel(logging.INFO)
def set_should_prune(self, flag):
""" Should Prune Setter """
self.should_prune = flag
def set_should_autostash(self, flag):
""" Autostash Setter """
self.should_autostash = flag
def set_create_logfile(self, flag):
""" Create Logfile Setter """
self.should_create_logfile = flag
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment