Package: gittools
AboutTools for getting information about git repositories in python, based ongitpython;gittoolsprovides functions to get quick commit information of paths / files:current_commit_hash()(returnstrof latest commit)path_status()(returndictwith more info, e.g. tags, dirty or not, etc.)There are also functions targeted for use on python modules that are within a git repository (e.g. following editable install from git clone):module_status(): similar topath_status()but with python module(s) as an input instead of a pathsave_metadata(): save git information and any other metadata provided as input into a JSON file.Other functions includerepo_tags()andpath_in_tree()(see below).See docstrings and information below for more details.InstallpipinstallgittoolsContentsSee help / docstrings of functions for details, andExamplessection below.General functionscurrent_commit_hash(path='.',checkdirty=True,checktree=True)commit hash (str) of HEAD commit of repository where path belongs; if True,checkdirtyandchecktreeraise exceptions if repo is dirty and if path does not belong to repo's tree, respectively.path_status(path='.')Similar tocurrent_commit_hash()but does not raise exceptions. Instead, returns git status (commit hash, dirty or clean, tag if there is one) as a dictionary.Functions for python modulesmodule_status(module,dirty_warning=False,dirty_ok=True,notag_warning=False,nogit_ok=False,nogit_warning=False)Version ofpath_status()adapted for python modules (module can be a single module or a list/iterable of modules). Data is returned as a dict of dicts where the keys are module names and the nested dicts correspond to dicts returned bypath_status().There is anogit_okoption to avoid raising an error if one or several modules are not in a git repository. In this case, the returned information of the module indicates that the module is not in a git repo and uses the module version number as a tag.Other options are to print warnings when:the repo is dirty, i.e. uncommitted (dirty_warning),it is missing a tag at the current commit (notag_warning),one or more modules are not in a git repo (nogit_warning).Ifdirty_okis set to False, aDirtyRepoexception is thrown if the module(s) have a dirty repository.save_metadata(file,info=None,module=None,dirty_warning=False,dirty_ok=True,notag_warning=False,nogit_ok=False,nogit_warning=False):Save metadata (infosdictionary), current time, and git module info. Themodule,dirty_warning,notag_warning,nogit_okandnogit_warningparameters are the same as formodule_status().Miscellaneous functionsrepo_tags(path='.'): lists all tags in repository the path belongs to, as a {'commit hash': 'tag name'} dictionary (both keys and values are strings).path_in_tree(path, commit): used bycurrent_commit_hash; returns True if path belongs to the commit's working tree (or is the root directory of repo), else False.ExceptionsThecheckdirtyandchecktreeoptions raise custom exceptions:DirtyRepoandNotInTree, respectively.Examples>>>fromgittoolsimportcurrent_commit_hash,repo_tags>>>current_commit_hash()# Most recent commit of the current working directory'1f37588eb5aadf802274fae74bc4abb77d9d8004'# Other possibilities>>>current_commit_hash(checkdirty=False)# same, but avoid raising DirtyRepo>>>current_commit_hash('gitrepos/repo1/foo.py')# same, but specify path/file# Note that the previous example will raise an exception if the file is not# tracked in a git repository. To silence the exception and see the most# recent commit hash of the closest git repository in a parent directory:>>>current_commit_hash('Test/untracked_file.pyc',checktree=False)# List all tags of repo:>>>repo_tags()# current directory, but also possible to specify path{'1f37588eb5aadf802274fae74bc4abb77d9d8004':'v1.1.8','b5173941c9cceebb786b0c046c67ea505786d820':'v1.1.9'}It can be easier to use higher level functions to get hash name, clean/dirty status, and tag (if it exists):>>>fromgittoolsimportpath_status,module_status>>>path_status()# current working directory (also possible to specify path){'hash':'1f37588eb5aadf802274fae74bc4abb77d9d8004','status':'clean','tag':'v1.1.8'}>>>importmypackage1# module with clean repo and tag at current commit>>>module_status(mypackage1){'mypackage1':{'hash':'1f37588eb5aadf802274fae74bc4abb77d9d8004','status':'clean','tag':'v1.1.8'}}>>>importmypackage2# this package has uncommitted changes and no tags>>>module_status(mypackage2,dirty_warning=True)Warning:thefollowingmoduleshavedirtygitrepositories:mypackage2{'mypackage2':{'hash':'8a0305e6c4e7a57ad7befee703c4905aa15eab23','status':'dirty'}}>>>module_status([mypackage1,mypackage2])# list of modules{'mypackage1':{'hash':'1f37588eb5aadf802274fae74bc4abb77d9d8004','status':'clean','tag':'v1.1.8'},'mypackage2':{'hash':'8a0305e6c4e7a57ad7befee703c4905aa15eab23','status':'dirty'}}# mypackage3 not a git repo>>>module_status([mypackage1,mypackage2,mypackage3],nogit_ok=True){'mypackage1':{'hash':'1f37588eb5aadf802274fae74bc4abb77d9d8004','status':'clean','tag':'v1.1.8'},'mypackage2':{'hash':'8a0305e6c4e7a57ad7befee703c4905aa15eab23','status':'dirty'},'mypackage3':{'status':'not a git repository','tag':'v1.3.2'}}Save metadata with current time and git info (frommodule_status())>>>importgittools,oclock,numpy>>>fromgittoolsimportsave_metadata>>>modules=gittools,aquasol>>>parameters={'temperature':25,'pressure':2338}>>>save_metadata('metadata.json',info=parameters,module=modules,nogit_ok=True)# Writes a .json file with the following info:{"temperature":25,"pressure":2338,"time (utc)":"2020-12-03 21:33:17","code version":{"gittools":{"hash":"12f2ceb3c5fffcc31e422474485e2481890a8094","status":"dirty","tag":"v0.3.1"},"oclock":{"hash":"826aa76e5096680805eb43fb22a80ccc3b282015","status":"clean","tag":"v1.0.1"}"numpy":{"status":"not a git repository","tag":"v1.19.2"}}}Requirements / dependenciesPythonPython >= 3.6Python packages(installed automatically by pip if necessary)gitpython (https://gitpython.readthedocs.io)importlib-metadataOthergit (see gitpython requirements for git minimal version)AuthorOlivier Vincent (ovinc.py@gmail.com)License3-Clause BSD (seeLICENSEfile)BSD 3-Clause LicenseCopyright (c) 2020, Olivier VINCENT
All rights reserved.Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.