Welcome to githelper’s documentation!¶
Introduction¶
Githelper is both a module and a command line utility for working with git working copies.
It is maintained at https://github.com/liyanage/git-tools/tree/master/githelper
The HTML version of this documentation is available at http://liyanage.github.com/git-tools/
Installation¶
You can install githelper directly from github like this:
sudo curl -o /usr/local/bin/githelper.py -L https://github.com/liyanage/git-tools/raw/master/githelper/githelper.py
sudo chmod 755 /usr/local/bin/githelper.py
Command Line Utility¶
This documentation does not cover the command line utility usage in detail because you can get that with the help option:
githelper.py -h
The utility is subcommand-based, and each subcommand has its own options. You can get a list of subcommands with the -h option shown above, and each subcommand in turn supports the -h flag:
githelper.py some_subcommand -h
You can extend the set of subcommands by writing plug-in classes. See Extending with Plug-In Classes for details.
You can abbreviate the subcommand name. The abbreviation does not have to be a contiguous prefix or substring of the full name, any sequence of characters that unanbiguously identifies one of the subcommands will work (it must be anchored at the beginning, however).
Command Line Utility Examples¶
Below are some command line usage examples. The examples assume a
gh
shell alias for githelper defined as follows:
$ alias gh githelper.py
To get an overview of the nested working copies, use the tree
subcommand:
$ gh tree
|<Working copy /path/to/my-great-project>
|--<Working copy /path/to/my-great-project/Foo *>
|----<Working copy /path/to/my-great-project/Foo/subexternal l*>
|--<Working copy /path/to/my-great-project/Bar>
|--<Working copy /path/to/my-great-project/Baz>
|--<Working copy /path/to/my-great-project/Subproject *>
|----<Working copy /path/to/my-great-project/Subproject/ABC/Demo>
|--<Working copy /path/to/my-great-project/Xyz>
The * indicates a working copy with uncommited changes. The l indicates a local-only branch, i.e. one that’s not tracking a remote branch
To get a combined git status view, use status
:
$ gh status
<Working copy /path/to/my-great-project/Foo *>
M data.txt
<Working copy /path/to/my-great-project/Subproject *>
A xyz.dat
Only working copies that have any interesting status are listed.
As a reminder, you could shorten the subcommand name and type just gh sta
here.
To check out a certain point in time in the past in all nested working copies, you could
use the each
subcommand, which runs a shell command in each one:
$ gh each "git checkout \$(git rev-list -n 1 --before='2012-01-01 00:00' master)"
Another useful subcommand is branch
, it gives a complete overview of the branch
status of each working copy:
$ gh b
branch
</Users/liyanage/Projects/foo> 0↑ 0↓ master 4c3b6721 1h
</Users/liyanage/Projects/foo/repositories/LibraryManager> 0↑ 0↓ master 301105f7 1h
</Users/liyanage/Projects/foo/repositories/Reports *> 0↑ 0↓ master 7ffa7408 2h
</Users/liyanage/Projects/foo/repositories/analyzer> 0↑ 0↓ feature/xyz c2881596 5h
</Users/liyanage/Projects/foo/repositories/common l> 0↑ 0↓ master f0a1ec75 34m
See the subcommand’s detailed help for an explanation of the columns.
Many subcommands, fetch
included, run the branch
subcommand automatically after they finish.
These are just a few examples, see the command line help for the remaining subcommands.
Usage as Toolkit Module¶
If the utility does not provide what you need, you can write your own script based on githelper as a module. The rest of this document explains the module’s API.
The main entry point is the GitWorkingCopy
class. You instantiate it
with the path to a git working copy (which possibly has nested sub-working copies).
You can then traverse the tree of nested working copies by iterating over the GitWorkingCopy instance:
#!/usr/bin/env python
import githelper
import os
import sys
root_wc = githelper.GitWorkingCopy(sys.argv[1])
for wc in root_wc:
# Gets called once for root_wc and all sub-working copies.
# Do something interesting with wc using its API here...
The traverse()
method provides another way to do this,
it takes a callable, in the following example a function:
def process_working_copy(wc):
print wc.current_branch()
root_wc = githelper.GitWorkingCopy(sys.argv[1])
root_wc.traverse(process_working_copy)
Any callable object works, in the following example an instance of a class that implements __call__()
:
class Foo:
def __init__(self, some_state):
self.some_state = some_state
def __call__(self, wc):
# possibly use self.some_state
print wc.current_branch()
root_wc = githelper.GitWorkingCopy(sys.argv[1])
iterator = Foo('bar')
root_wc.traverse(iterator)
You can take a look at the various Subcommand...
classes in the module’s
source code to see examples of the API usage. These classes implement the various
subcommands provided by the command line utility front end and they exercise most of
the GitWorkingCopy
API.
Extending with Plug-In Classes¶
To extend the command line utility with additional custom subcommands, create a
file called githelper_local.py
and store it somewhere in your PATH
.
The file must contain one class per subcommand. Each class name must start with
Subcommand
, anything after that part is used as the actual subcommand name
that you pass on the command line to invoke it.
Here is an example githelper_local.py
with one subcommand named foo
:
from githelper import AbstractSubcommand, GitWorkingCopy
class SubcommandFoo(AbstractSubcommand):
# The class-level doc comment is reused for the command-line usage help string.
"""Provide a useful description of this subcommand here"""
def __call__(self, wc):
print wc
return GitWorkingCopy.STOP_TRAVERSAL
@classmethod
def configure_argument_parser(cls, parser):
# Add any command line options here. If you don't need any, just add a "pass" statement instead.
parser.add_argument('-b', '--bar', help='Provide a useful description of this option here')
API Documentation¶
-
class
githelper.
GitWorkingCopy
(path, parent=None, verbose=False)[source]¶ A class to represent a git working copy.
Parameters: - path (str) – The file system path to the working copy.
- parent (githelper.GitWorkingCopy) – A parent instance, you don’t usually use this yourself.
-
STOP_TRAVERSAL
= False¶ returned from a
__call__()
implementation to stop further recursion bytraverse()
.
-
__init__
(path, parent=None, verbose=False)[source]¶ x.__init__(…) initializes x; see help(type(x)) for signature
-
__iter__
()[source]¶ Returns an iterator over
self
and all of its nested git working copies.See the example above.
-
ancestors
()[source]¶ Returns a list of parent working copies.
If the receiver is the root working copy, this returns an empty list.
-
chdir_to_path
(**kwds)[source]¶ A context manager for the
with
statement that temporarily switches the current working directory to the receiver’s working copy directory:with wc.chdir_to_path(): # do something useful here inside the working copy directory.
-
commits_not_in_upstream
()[source]¶ Returns a list of git commits that have not yet been pushed to upstream.
-
commits_only_in_upstream
()[source]¶ Returns a list of git commits that are only in upstream but not in the local tracking branch.
-
create_stash_and_reset_hard
()[source]¶ Stashes the uncommitted changes in the working copy using “stash create”, i.e. without updating the “stash” reference, and runs “git reset –hard”. Prints and returns the commit id if anything was stashed, None otherwise.
-
dirty_file_lines
()[source]¶ Returns the output of git status for the files marked as modified, renamed etc.
-
has_branch
(branch_name)[source]¶ Returns True if the working copy has a git branch with the given name
-
is_dirty
()[source]¶ Returns True if the receiver’s working copy has uncommitted modifications.
Many operations depend on a clean state.
-
output_for_git_command
(command, shell=False, filter_rules=None, header=None, check_returncode=None, echo_stderr=True)[source]¶ Runs the given shell command (array or string) in the receiver’s working directory and returns the output.
Parameters: shell (bool) – If True
, runs the command through the shell. See thesubprocess
library module documentation for details.
-
remote_branch_name_for_name_list
(name_list)[source]¶ Returns a remote branch name matching a list of candidate strings.
Tries to find a remote branch names using all possible combinations of the names in the list. For example, given:
['foo', 'bar']
as
name_list
, it would find any of these:remotes/foo remotes/Foo remotes/bar remotes/Bar remotes/Foo-Bar remotes/foo-bar remotes/Bar-Foo remotes/bar-foo
etc. and return the part after
remotes/
of the first match.
-
remote_branch_names
()[source]¶ Returns a list of git branch names starting with
remote/
.The leading
remote/
part will be removed.
-
run_shell_command
(command, filter_rules=None, shell=None, header=None, check_returncode=True)[source]¶ Runs the given shell command (array or string) in the receiver’s working directory using
FilteringPopen
.Parameters: - command (str) – Passed to
FilteringPopen
’s constructor. Can also be an array. - filter_rules (array) – Passed to
FilteringPopen
’s constructor. - shell (bool) – Passed to
FilteringPopen
’s constructor. - header (object) – Passed to
FilteringPopen.run
.
- command (str) – Passed to
-
self_or_descendants_dirty_working_copies
()[source]¶ Returns True if the receiver’s or one of its nested working copies are dirty.
Parameters: list_dirty (bool) – If True
, prints the working copy path and the list of dirty files.
-
switched_to_branch
(**kwds)[source]¶ A context manager for the
with
statement that temporarily switches the current git branch to another one and afterwards restores the original one.Example:
with wc.switched_to_branch('master'): # do something useful here on the 'master' branch.
Returns a list of tags that point to the given commit
Returns a list of tags that point to the head commit
-
traverse
(iterator)[source]¶ Runs the given callable
iterator
on the receiver and all of its nested sub-working copies.Before each call to iterator for a given working copy, the current directory is first set to that working copy’s path.
See the example above.
-
class
githelper.
FilteringPopen
(*args, **kwargs)[source]¶ A wrapper around
subprocess.Popen
that filters the subprocess’s output.The constructor’s parameters are forwarded mostly unchanged to
Popen's constructor
. Exceptions arebufsize
, which is set to1
for line-buffered output, andstdout
, andstderr
, which are both set tosubprocess.PIPE
.This method sets up the Popen instance but does not run it. See
run()
for that.-
run
(filter=None, filter_rules=None, store_stdout=True, store_stderr=True, echo_stdout=True, echo_stderr=True, check_returncode=True, header=None)[source]¶ Run the command and capture its (potentially filtered) output, similar to
subprocess.Popen.communicate()
.Parameters: - filter (githelper.PopenOutputFilter) – An optional filter for stderr and stdout.
- filter_rules (array) – Instead of a
PopenOutputFilter
instance, you can also pass a rule set directly. - store_stdout (bool) – If
False
, the command’s output will not be stored for later retrieval. If set toTrue
, the output can be retrieved through thestdoutlines()
method after it has finished executing. - store_stderr (bool) – If
False
, the command’s output will not be stored for later retrieval. If set toTrue
, the output can be retrieved through thestderrlines()
method after it has finished executing. - echo_stdout (bool) – If
False
, the command’s output will not be printed to stdout. - echo_stderr (bool) – If
False
, the command’s output will not be printed to stderr. - check_returncode (bool) – If
True
, the method raises an exception if the command terminates with a non-zero exit code. - header (object) – This value will be printed to the console exactly once if the subcommand produces any output that does not get filtered out. This is useful if you want to print something, but not if the command would not produce any output anyway.
-
-
class
githelper.
PopenOutputFilter
(stdout_rules, stderr_rules=None)[source]¶ Represents a set of inclusion/exclusion rules to filter the output of
FilteringPopen
. You create instance of this class to pass toFilteringPopen.run()
(but seerun()
’sfilter_rules
parameter for a convenience shortcut).There are two independent rule sets to filter stdout and stderr individually. If you don’t supply the (optional) rule set for stderr, the (mandatory) one for stdout is reused.
Rule sets are lists of lists of this form:
rules = [ ('-', r'^foo'), ('-', r'bar$'), ... ]
Each rule is a two-element list where the first element is either the string “-” or “+” representing the actions for exclusion and inclusion, and the second element is a regular expression.
Each line of stdout or stderr output is matched against each regular expression. If one of them matches, the line is filtered out if the action element is “-” or included if the action is “+”. After the first rule matches, no further rules are evaluated.
If no rule matches a given line, the line is included (not filtered out), i.e. there is an implicit last rule like this:
('+', '.*')
In the example given above, all lines beginning with
foo
or ending withbar
are filtered out.In the following example, only lines containing foo or bar are included, everything else is filtered out:
rules = [ ('+', r'foo'), ('+', r'bar'), ('-', '.*') ]
-
class
githelper.
AbstractSubcommand
(arguments)[source]¶ A base class for custom subcommand plug-in classes.
You can, but don’t have to, derive from this class for your custom subcommand extension classes. It also documents the interface you are expected to implement in your class and it provides some convenience methods.
Parameters: arguments (argparse.Namespace) – The command-line options passed to your subcommand in the form of a namespace instance as returned by argparse.ArgumentParser.parse_args()
.-
__call__
(wc=None)[source]¶ This gets called once per working copy to perform the subcommand’s task.
If you are only interested in the root-level working copy, you can stop the traversal by returning
githelper.GitWorkingCopy.STOP_TRAVERSAL
.Parameters: wc (githelper.GitWorkingCopy) – The working copy to process.
-
chained_post_traversal_subcommand_for_root_working_copy
(root_wc)[source]¶ This method gets called on the root working copy after the traversal of a tree has finished. The subcommand class can return another subcommand instance that will be run next.
Parameters: root_wc (githelper.GitWorkingCopy) – The working copy to process.
-
classmethod
configure_argument_parser
(parser)[source]¶ If you override this in your subclass, you can configure additional command line arguments for your subcommand’s arguments parser.
Parameters: parser (argparse.ArgumentParser) – The argument parser that you can configure.
-
prepare_for_root
(root_wc)[source]¶ This method gets called on the root working copy only and lets you perform preparation steps that you want to do only once for the entire tree.
Parameters: root_wc (githelper.GitWorkingCopy) – The working copy to check.
-