diff --git a/gitinspector/clone.py b/gitinspector/clone.py index 053f99d..a1cae4b 100644 --- a/gitinspector/clone.py +++ b/gitinspector/clone.py @@ -18,27 +18,41 @@ # along with gitinspector. If not, see . from __future__ import unicode_literals +from collections import namedtuple +import os import shutil import subprocess import sys import tempfile +try: + from urllib.parse import urlparse +except: + from urlparse import urlparse + __cloned_paths__ = [] def create(url): - if url.startswith("file://") or url.startswith("git://") or url.startswith("http://") or \ - url.startswith("https://") or url.startswith("ssh://"): - location = tempfile.mkdtemp(suffix=".gitinspector") - git_clone = subprocess.Popen(["git", "clone", url, location], bufsize=1, stdout=sys.stderr) + class Repository(object): + def __init__(self, name, location): + self.name = name + self.location = location + + parsed_url = urlparse(url) + + if parsed_url.scheme == "file" or parsed_url.scheme == "git" or parsed_url.scheme == "http" or \ + parsed_url.scheme == "https" or parsed_url.scheme == "ssh": + path = tempfile.mkdtemp(suffix=".gitinspector") + git_clone = subprocess.Popen(["git", "clone", url, path], bufsize=1, stdout=sys.stderr) git_clone.wait() if git_clone.returncode != 0: sys.exit(git_clone.returncode) - __cloned_paths__.append(location) - return location + __cloned_paths__.append(path) + return Repository(os.path.basename(parsed_url.path), path) - return url + return Repository(None, os.path.abspath(url)) def delete(): for path in __cloned_paths__: diff --git a/gitinspector/format.py b/gitinspector/format.py index b4f2a5a..c3a24cc 100644 --- a/gitinspector/format.py +++ b/gitinspector/format.py @@ -24,6 +24,7 @@ import os import textwrap import time import zipfile +from .localization import N_ from . import basedir, localization, terminal, version __available_formats__ = ["html", "htmlembedded", "json", "text", "xml"] @@ -59,7 +60,12 @@ def __get_zip_file_content__(name, file_name="/html/flot.zip"): zip_file.close() return content.decode("utf-8", "replace") -def output_header(repo): +INFO_ONE_REPOSITORY = N_("Statistical information for the repository '{0}' was gathered on {1}.") +INFO_MANY_REPOSITORIES = N_("Statistical information for the repositories '{0}' was gathered on {1}.") + +def output_header(repos): + repos_string = ", ".join([repo.name for repo in repos]) + if __selected_format__ == "html" or __selected_format__ == "htmlembedded": base = basedir.get_basedir() html_header = __output_html_template__(base + "/html/html.header") @@ -80,7 +86,7 @@ def output_header(repo): else: jquery_js = " src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js\">" - print(html_header.format(title=_("Repository statistics for {0}").format(os.path.basename(repo)), + print(html_header.format(title=_("Repository statistics for '{0}'").format(repo_string), jquery=jquery_js, jquery_tablesorter=tablesorter_js, jquery_flot=flot_js, @@ -91,8 +97,8 @@ def output_header(repo): " for git repositories.").format( "gitinspector", version.__version__), - repo_text=_("Statistical information for the repository '{0}' was gathered on {1}.").format( - os.path.basename(repo), localization.get_date()), + repos_text=_(INFO_ONE_REPOSITORY if len(repos) <= 1 else INFO_MANY_REPOSITORIES).format( + repos_string, localization.get_date()), show_minor_authors=_("Show minor authors"), hide_minor_authors=_("Hide minor authors"), show_minor_rows=_("Show rows with minor work"), @@ -102,11 +108,11 @@ def output_header(repo): elif __selected_format__ == "xml": print("") print("\t" + version.__version__ + "") - print("\t" + os.path.basename(repo) + "") + print("\t" + repos_string + "") print("\t" + time.strftime("%Y/%m/%d") + "") else: - print(textwrap.fill(_("Statistical information for the repository '{0}' was gathered on {1}.").format( - os.path.basename(repo), localization.get_date()), width=terminal.get_size()[0])) + print(textwrap.fill(_(INFO_ONE_REPOSITORY if len(repos) <= 1 else INFO_MANY_REPOSITORIES).format( + repos_string, localization.get_date()), width=terminal.get_size()[0])) def output_footer(): if __selected_format__ == "html" or __selected_format__ == "htmlembedded": diff --git a/gitinspector/gitinspector.py b/gitinspector/gitinspector.py index ad4aff3..13478b2 100644 --- a/gitinspector/gitinspector.py +++ b/gitinspector/gitinspector.py @@ -60,15 +60,12 @@ class Runner(object): terminal.skip_escapes(not sys.stdout.isatty()) terminal.set_stdout_encoding() previous_directory = os.getcwd() - summed_blames = None summed_changes = None summed_metrics = None for repo in repos: - os.chdir(previous_directory) - os.chdir(repo) - absolute_path = basedir.get_basedir_git() + os.chdir(repo.location) changes = Changes(self.hard) summed_blames = Blame(self.hard, self.useweeks, changes) + summed_blames summed_changes = changes + summed_changes @@ -78,10 +75,10 @@ class Runner(object): if sys.stdout.isatty() and format.is_interactive_format(): terminal.clear_row() + else: + os.chdir(previous_directory) - os.chdir(absolute_path) - - format.output_header(absolute_path) + format.output_header(repos) outputable.output(ChangesOutput(changes)) if changes.get_commits(): @@ -109,6 +106,24 @@ def __check_python_version__(): python_version = str(sys.version_info[0]) + "." + str(sys.version_info[1]) sys.exit(_("gitinspector requires at least Python 2.6 to run (version {0} was found).").format(python_version)) +def __get_validated_git_repos__(repos_relative): + if not repos_relative: + repos_relative = "." + + repos = [] + + #Try to clone the repos or return the same directory and bail out. + for repo in repos_relative: + cloned_repo = clone.create(repo) + basedir_path = basedir.get_basedir_git(cloned_repo.location) + + if cloned_repo.name == None: + cloned_repo.name = os.path.basename(basedir_path) + + repos.append(cloned_repo) + + return repos + def main(): terminal.check_terminal_encoding() terminal.set_stdin_encoding() @@ -121,13 +136,10 @@ def main(): "hard:true", "help", "list-file-types:true", "localize-output:true", "metrics:true", "responsibilities:true", "since=", "grading:true", "timeline:true", "until=", "version", "weeks:true"]) + repos = __get_validated_git_repos__(set(args)) - #Try to clone the repos or return the same directory and bail out. - for repo in args: - repos.append(clone.create(repo)) - - #We need the repo above to be set before we read the git config. - GitConfig(run, repos[-1] if len(repos) > 0 else ".", len(repos) > 1).read() + #We need the repos above to be set before we read the git config. + GitConfig(run, repos[-1].location).read() clear_x_on_next_pass = True for o, a in opts: @@ -190,7 +202,7 @@ def main(): filtering.add(a) __check_python_version__() - run.process(["."] if repos == [] else repos) + run.process(repos) except (filtering.InvalidRegExpError, format.InvalidFormatError, optval.InvalidOptionArgument, getopt.error) as exception: print(sys.argv[0], "\b:", exception.msg, file=sys.stderr)