Commits

Troy Williams  committed a8ebf1b

Refactored hg_utilities.py. It is now simpler and a bit easier to understand.

Refactored HgHelper.py

SubprocessHelper.py - added a call to strip() on the output stream and error
stream so that empty lines and extra whitespace is removed.

  • Participants
  • Parent commits 25fc5f4

Comments (0)

Files changed (3)

 
 """
 
+contains various implementations that are useful in dealing with mercurial
+repositories.
+
 Copyright (c) 2011 Troy Williams
 
 License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
 
 class Repository():
 
-    def __init__(self, path):
-        self.path = path
-        self.name = os.path.basename(path)
-        self.parent_path = os.path.dirname(path)
-        self.parent_path_name = os.path.basename(self.parent_path)
-        self.relative_name = os.path.join(self.parent_path_name, self.name)
+    def __init__(self, repo_path):
+        self.path = repo_path
+        self.name = os.path.basename(repo_path)
         self.commands = {'update':['hg', 'update']}
         self.commands['push'] = ['hg', 'push']
         self.commands['pull'] = ['hg', 'pull']
         self.commands['status'] = ['hg', 'status']
         self.commands['incoming'] = ['hg', 'incoming']
         self.commands['outgoing'] = ['hg', 'outgoing']
-        self.command_result = ()
 
     def run_repo_command(self, command):
         """
         m = 'abort: repository default not found!'
         return not m in self.standard_output_stream[0]
 
-#    def has_incoming_changes(self):
-#        """
-#        ['comparing with https://troy_williams:***@bitbucket.org/troy_williams/source_code',
-#        'searching for changes',
-#        'no changes found',
-#        '']
-#        """
-#
-#        self.incoming()
-#        m = 'no changes found'
-#        return not m in self.standard_output_stream[2]
-
     def supports_outgoing(self):
         """
         Interprets the hg outgoing command and determines if the repository is
 
 def find_repositories(path):
     """
-    Takes a path and searches it for mecurial repositories. It returns a list of
-    repository objects.
+    Generator to search a path for mercurial repositories.
     """
 
-    path_to_search = path
     repository_folder_indicator = '.hg'
-    repositories = []
 
-    for current_path, dirs, files in os.walk(path_to_search):
+    for current_path, dirs, files in os.walk(path):
         if repository_folder_indicator in dirs:
-            repositories.append(Repository(current_path))
-            dirs[:] = []
-
-    return repositories
+            dirs[:] = [] #no point in searching the branch any further
+            yield current_path

File SubprocessHelper.py

 #-*- coding:utf-8 -*-
 
 """
-
-
+Contains code that helps in dealing with the subprocess module.
 
 Links:
 http://docs.python.org/library/subprocess.html
         output_stream, error_stream = p.communicate()
 
         if output_stream:
-            self.standard_output_stream = output_stream.split('\n')
+            self.standard_output_stream = output_stream.strip().split('\n')
 
         if error_stream:
-            self.standard_error_stream = error_stream.split('\n')
+            self.standard_error_stream = error_stream.strip().split('\n')

File hg_utilities.py

 import os
 import HgHelper
 
-
 __uuid__ = 'ca635163-d33d-4e18-a8d0-53039bea6f18'
 __author__ = 'Troy Williams'
 __email__ = 'troy.williams@bluebill.net'
 __copyright__ = 'Copyright (c) 2011, Troy Williams'
-__version__ = '0.5'
-
-
-#def find_repositories(root):
-#    """
-#    Search for mecurial repositories and returns the paths that are found.
-
-#    It will not continue to search a path once it is determined that a path is a
-#    repository.
-#    """
-
-#    path_to_search = root
-#    repository_folder_indicator = '.hg'
-#    hg_repositories = []
-#    for current_path, dirs, files in os.walk(path_to_search):
-#        if repository_folder_indicator in dirs:
-#            print 'Found repository: %s' % os.path.relpath(current_path,root)
-#            hg_repositories.append(current_path)
-#            dirs[:] = [] #clear the list of directorys so we stop searching this branch
-
-#    return hg_repositories
+__version__ = '0.6'
 
 
 def process_command_line():
 
     return options, args
 
-#def run_command(command, working_directory, useshell=False):
-#    """
-#    Takes the list and attempts to run it in the command shell and waits for it
-#    to execute. It then returns the results to the caller.
-#    """
+def print_repo_error(repo):
+    """
+    Print the repo standard error stream to the standard output.
+    """
+    print repo.standard_error_stream
 
-#    subprocess_helper = SubprocessHelper()
-#    subprocess_helper.run(command, shell=useshell, working_directory=working_directory)
-#    return subprocess_helper.standard_output_stream, subprocess_helper.standard_error_stream
+def has_repo_error_occured(repo):
+    """
+    If an error has occured with the last command issued to the repository, the
+    error stream should contain something. This routine will true if an error
+    occurred.
+    """
+    if repo.standard_error_stream:
+        return True
+    else:
+        return False
 
-
-#def hg_update(hg_repository):
-#    """
-#    Execute the hg update command on the repository
-#    """
-#    cmd = ['hg', 'update']
-#    return run_command(cmd, hg_repository) #tuple of (std.output, std.error)
-
-
-#def hg_push(hg_repository):
-#    """
-#    Execute the hg push command on the repository
-#    """
-#    cmd = ['hg', 'push']
-#    return run_command(cmd, hg_repository) #tuple of (std.output, std.error)
-
-
-#def hg_pull(hg_repository):
-#    """
-#    Issues the hg pull command on the specified repository
-#    """
-#    cmd = ['hg', 'pull']
-#    return run_command(cmd, hg_repository) #tuple of (std.output, std.error)
-
-
-#def hg_status(hg_repository):
-#    """
-#    Issues the hg status command on the specified repository. If anything is
-#    returned then the repository has a pending commit and should not have any
-#    push or pull operations performed on it.
-#    """
-#    cmd = ['hg', 'status']
-#    return run_command(cmd, hg_repository) #tuple of (std.output, std.error)
-
-
-#def hg_incomming(hg_repository):
-#    """
-#    issues an hg incoming command on the repository
-
-#    $ hg incoming
-#    comparing with /home/troy/tmp/repos/repo1
-#    searching for changes
-#    no changes found
-
-#    $ hg incoming
-#    abort: repository default not found!
-
-
-#    $ hg incoming
-#    comparing with /home/troy/tmp/repos/repo1
-#    searching for changes
-#    changeset:   1:f4e4c8ffd56b
-#    tag:         tip
-#    user:        Troy Williams <troy.williams@bluebill.net>
-#    date:        Sat Oct 22 14:52:31 2011 -0400
-#    summary:     added a file
-#    """
-
-#    cmd = ['hg', 'incoming']
-#    return run_command(cmd, hg_repository) #tuple of (std.output, std.error)
-
-#def find_pending_commits(repositories):
-#    """
-#    Searches each repository for pending commits. If any are found the repository
-#    is added to a new list and returned
-#    """
-
-#    pending_commits = []
-#    for repo in repositories:
-#        output, error = hg_status(repo)
-#        if output:
-#            pending_commits.append(repo)
-
-#    return pending_commits
-
-#def is_remote_incoming_repo_setup(hg_incoming_message):
-#    """
-#    interprets the hg incomming message and determines if the repo has a remote
-#    repository setup
-
-#    hg_incoming_message is a tuple of (std.output, std.error). Check to see
-#    if there is the abort message
-#    """
-
-#    m = 'abort: repository default not found!'
-#    return m in hg_incoming_message[1]
-
-
-#def update_repositories(repositories):
-#    """
-#    Takes the list of repositories and updates them
-#    """
-#    for repo in repositories:
-#        print 'updating', repo
-#        output, error = hg_update(repo)
-#        if error:
-#            print error
-#            continue
-
-#        print output
-
-#def pull_repository_changes(repositories):
-#    """
-#    Takes the list of repositories and pulls the changes
-#    """
-#    for repo in repositories:
-#        print 'Pulling changes for', repo
-#        output, error = hg_pull(repo)
-#        if error:
-#            print error
-#            continue
-
-#def find_repos_with_default_incoming_sync(repositories):
-#    """
-#    Takes a list of repositories and finds the ones that are configured to pull
-#    remote changes.
-#    """
-#    repos_with_sync_capabilities = []
-#    for repo in repositories:
-#        status = hg_incomming(repo) #status is a tuple (std, stderr)
-#        if is_remote_incoming_repo_setup(status):
-#            print repo, 'is not configured for synchronization'
-#        else:
-#            repos_with_sync_capabilities.append(repo)
-
-#    return repos_with_sync_capabilities
-
-#def pull_changes_and_update(repositories):
-#    """
-#    Takes the repositories and pulls remote changes and then updates them
-#    """
-
-#    repos_with_sync_capabilities = find_repos_with_default_incoming_sync(repositories)
-#    pull_repository_changes(repos_with_sync_capabilities)
-#    update_repositories(repos_with_sync_capabilities)
-
-#def push_repository_changes(repositories):
-#    """
-#    Takes the list of repositories and pushes the changes
-#    """
-#    for repo in repositories:
-#        print 'Pushing changes for', repo
-#        output, error = hg_push(repo)
-#        if error:
-#            print error
-#            continue
-
-def print_repositories(repositories, path):
+def pull_update_repo(repo):
     """
-    Takes a list of repositores and a common path and displays the name
-    of each repository.
+    Issues a pull then update command against the repository.
     """
 
-    for repo in repositories:
-        print '%s' % os.path.relpath(repo.path, path)
+    if not pull_repo(repo):
+        return
 
-def find_pending_commits(repositories):
+    update_repo(repo)
+
+
+def pull_repo(repo):
     """
-    Searches each repository for pending commits. If any are found the repository
-    is added to a new list and returned
+    Issues a pull command against the repository.
     """
 
-    pending_commits = []
-    for repo in repositories:
-        if repo.has_pending_commits():
-            pending_commits.append(repo)
+    if repo.supports_incoming():
+        print 'Pulling changes for %s' % repo.relative_repo_path
+        repo.pull()
+        if has_repo_error_occured(repo):
+            print_repo_error(repo)
+            return False
+        return True
 
-    return pending_commits
+    return False
 
-def pull_repository_changes(repositories):
+def push_repo(repo):
     """
-    Pulls the changes for the repositories in the list
-    """
-    for repo in repositories:
-        print 'Pulling changes for %s' % repo.name
-        repo.pull()
-        if repo.standard_error_stream:
-            print repo.standard_error_stream
-            continue
-
-            print repo.standard_output_stream
-
-def push_repository_changes(repositories):
-    """
-    Pushes the repository changes
-    """
-    for repo in repositories:
-        print 'Pushing changes for %s' % repo.name
-        repo.push()
-        if repo.standard_error_stream:
-            print repo.standard_error_stream
-            continue
-
-            print repo.standard_output_stream
-
-def update_repositories(repositories):
-    """
-    Updates the repositories
-    """
-    for repo in repositories:
-        print 'Updating %s' % repo.name
-        repo.update()
-        if repo.standard_error_stream:
-            print repo.standard_error_stream
-            continue
-
-            print repo.standard_output_stream
-
-def pull_changes_and_update(repositories):
-    """
-    Takes the repositories and pulls remote changes and then updates them
+    Issues a pull command against the repository.
     """
 
-    for repo in repositories:
+    if repo.supports_outgoing():
+        print 'Pushing changes for %s' % repo.relative_repo_path
+        repo.push()
+        if has_repo_error_occured(repo):
+            print_repo_error(repo)
+            return False
+        return True
 
-        if repo.supports_incoming():
-            print 'Pulling and updating changes for %s' % repo.relative_name
-            repo.pull()
-            if repo.standard_error_stream:
-                print repo.standard_error_stream
-                continue
+    return False
 
-            repo.update()
-            if repo.standard_error_stream:
-                print repo.standard_error_stream
-                continue
 
-            print ' '.join(repo.standard_output_stream)
+def update_repo(repo):
+    """
+    Issues an update command against the repository.
+    """
+
+    print 'Updating %s' % repo.relative_repo_path
+    repo.update()
+    if has_repo_error_occured(repo):
+        print_repo_error(repo)
+        return False
+
+    print ' '.join(repo.standard_output_stream)
+    return True
+
+
+def process_repo_based_on_options(repo, options):
+    """
+    Determines what to do with the repository based on the user defined options.
+    """
+
+    if options.pullupdate:
+        pull_update_repo(repo)
+
+    elif options.pull:
+        pull_repo(repo)
+
+    elif options.push:
+        push_repo(repo)
+
+    elif options.update:
+        update_repo(repo)
+
+    else:
+        print parser.print_help()
+
 
 def main():
     """
-    Parse the command line and issue the appropriate mercurial command.
+    Search for the repositories in the given path(s). Process the found repo(s)
+    based on the user defined options.
     """
 
     options, args = process_command_line()
 
-    search_paths = []
     for arg in args:
-        search_paths.append(os.path.abspath(arg))
+        path = os.path.abspath(arg)
+        print 'Searching %s...' % path
 
-    if not search_paths:
-        raise Exception('No search paths found!')
+        for repo_path in HgHelper.find_repositories(path):
+            repo = HgHelper.Repository(repo_path)
+            repo.relative_repo_path = os.path.relpath(repo.path, path)
+            print 'Found: ', repo.relative_repo_path
 
-    repositories = []
-    for path in search_paths:
-        print 'Searching %s...' % path
-        found_repositories = HgHelper.find_repositories(path)
-        if found_repositories:
-            print 'Found Repositories:'
-            print_repositories(found_repositories, path)
-            repositories.extend(found_repositories)
+            if repo.has_pending_commits():
+                print repo.relative_repo_path, 'has pending commits:'
+                print '\n'.join(repo.standard_output_stream)
+                continue
 
-    pending_commits = find_pending_commits(repositories)
-    if pending_commits:
-        repositories = [p for p in repositories if p not in pending_commits]
-        for repo in pending_commits:
-            print repo.relative_name, 'has pending commits.'
-            print '\n'.join(repo.standard_output_stream)
+            process_repo_based_on_options(repo, options)
+            print ''
+    return 0
 
-    if len(repositories) == 0:
-        return -1
-
-#At this point we have a list of repositories that do not have pending commits
-    if options.pullupdate:
-        pull_changes_and_update(repositories)
-
-    elif options.pull:
-        pull_repository_changes(repositories)
-
-    elif options.push:
-        push_repository_changes(repositories)
-
-    elif options.update:
-        update_repositories(repositories)
-
-    else:
-        print parser.print_help()
-        return -1
-
-    return 0 # success
 
 if __name__ == '__main__':
     status = main()