This module provides a python interface to Sage’s git repository.
AUTHORS:
Bases: sage.dev.git_interface.GitProxy
A proxy object to wrap calls to git.
Calls to git show output to stdout and stderr as if the command was executed directly and raise an error on a non-zero exit code.
EXAMPLES:
sage: dev.git.echo.status() # not tested
Bases: sage.dev.git_interface.ReadStdoutGitProxy
A wrapper around the git command line tool.
Most methods of this class correspond to actual git commands. Some add functionality which is not directly available in git. However, all of the methods should be non-interactive. If interaction is required the method should live in saged.dev.sagedev.SageDev.
EXAMPLES:
sage: from sage.dev.test.config import DoctestConfig
sage: from sage.dev.user_interface import UserInterface
sage: from sage.dev.git_interface import GitInterface
sage: config = DoctestConfig()
sage: GitInterface(config['git'], UserInterface(config['UI']))
GitInterface()
Clean the working directory.
This is a convenience wrapper for git clean
INPUT:
EXAMPLES:
Create a GitInterface for doctesting:
sage: from sage.dev.git_interface import GitInterface
sage: from sage.dev.test.config import DoctestConfig
sage: from sage.dev.test.user_interface import DoctestUserInterface
sage: config = DoctestConfig()
sage: git = GitInterface(config["git"], DoctestUserInterface(config["UI"]))
Set up some files/directories:
sage: os.chdir(config['git']['src'])
sage: open('tracked','w').close()
sage: git.silent.add('tracked')
sage: with open('.gitignore','w') as f: f.write('ignored\nignored_dir')
sage: git.silent.add('.gitignore')
sage: git.silent.commit('-m', 'initial commit')
sage: os.mkdir('untracked_dir')
sage: open('untracked_dir/untracked','w').close()
sage: open('untracked','w').close()
sage: open('ignored','w').close()
sage: os.mkdir('ignored_dir')
sage: open('ignored_dir/untracked','w').close()
sage: with open('tracked','w') as f: f.write('version 0')
sage: git.echo.status()
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: tracked
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# untracked
# untracked_dir/
no changes added to commit (use "git add" and/or "git commit -a")
Some invalid combinations of flags:
sage: git.clean_wrapper(
....: remove_untracked_files=False, remove_untracked_directories=True)
Traceback (most recent call last):
...
ValueError: remove_untracked_directories only valid if remove_untracked_files is set
sage: git.clean_wrapper(remove_untracked_files = False, remove_ignored = True)
Traceback (most recent call last):
...
ValueError: remove_ignored only valid if remove_untracked_files is set
Per default only the tracked modified files are reset to a clean state:
sage: git.clean_wrapper()
sage: git.echo.status()
# On branch master
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# untracked
# untracked_dir/
nothing added to commit but untracked files present (use "git add" to track)
Untracked items can be removed by setting the parameters:
sage: git.clean_wrapper(remove_untracked_files=True)
Removing untracked
sage: git.clean_wrapper(
....: remove_untracked_files=True, remove_untracked_directories=True)
Removing untracked_dir/
sage: git.clean_wrapper(
....: remove_untracked_files=True, remove_ignored=True)
Removing ignored
sage: git.clean_wrapper(
....: remove_untracked_files=True,
....: remove_untracked_directories=True,
....: remove_ignored=True)
Removing ignored_dir/
Return the commit id of the local branch, or None if the branch does not exist
EXAMPLES:
Create a GitInterface for doctesting:
sage: import os
sage: from sage.dev.git_interface import GitInterface
sage: from sage.dev.test.config import DoctestConfig
sage: from sage.dev.test.user_interface import DoctestUserInterface
sage: config = DoctestConfig()
sage: git = GitInterface(config["git"], DoctestUserInterface(config["UI"]))
Create some branches:
sage: os.chdir(config['git']['src'])
sage: git.silent.commit('-m','initial commit','--allow-empty')
sage: git.silent.branch('branch1')
sage: git.silent.branch('branch2')
Check existence of branches:
sage: git.commit_for_branch('branch1') # random output
'087e1fdd0fe6f4c596f5db22bc54567b032f5d2b'
sage: git.commit_for_branch('branch2') is not None
True
sage: git.commit_for_branch('branch3') is not None
False
Return the commit id of the ref, or None if the ref does not exist.
EXAMPLES:
Create a GitInterface for doctesting:
sage: import os
sage: from sage.dev.git_interface import GitInterface
sage: from sage.dev.test.config import DoctestConfig
sage: from sage.dev.test.user_interface import DoctestUserInterface
sage: config = DoctestConfig()
sage: git = GitInterface(config["git"], DoctestUserInterface(config["UI"]))
Create some branches:
sage: os.chdir(config['git']['src'])
sage: git.silent.commit('-m','initial commit','--allow-empty')
sage: git.silent.branch('branch1')
sage: git.silent.branch('branch2')
Check existence of branches:
sage: git.commit_for_ref('refs/heads/branch1') # random output
'087e1fdd0fe6f4c596f5db22bc54567b032f5d2b'
sage: git.commit_for_ref('refs/heads/branch2') is not None
True
sage: git.commit_for_ref('refs/heads/branch3') is not None
False
Return the current branch
EXAMPLES:
Create a GitInterface for doctesting:
sage: import os
sage: from sage.dev.git_interface import GitInterface
sage: from sage.dev.test.config import DoctestConfig
sage: from sage.dev.test.user_interface import DoctestUserInterface
sage: config = DoctestConfig()
sage: git = GitInterface(config["git"], DoctestUserInterface(config["UI"]))
Create some branches:
sage: os.chdir(config['git']['src'])
sage: git.silent.commit('-m','initial commit','--allow-empty')
sage: git.silent.commit('-m','second commit','--allow-empty')
sage: git.silent.branch('branch1')
sage: git.silent.branch('branch2')
sage: git.current_branch()
'master'
sage: git.super_silent.checkout('branch1')
sage: git.current_branch()
'branch1'
If HEAD is detached:
sage: git.super_silent.checkout('master~')
sage: git.current_branch()
Traceback (most recent call last):
...
DetachedHeadError: unexpectedly, git is in a detached HEAD state
Get the current state of merge/rebase/am/etc operations.
OUTPUT:
A tuple of strings which consists of any of the following: 'rebase', 'am', 'rebase-i', 'rebase-m', 'merge', 'bisect', 'cherry-seq', 'cherry'.
EXAMPLES:
Create a GitInterface for doctesting:
sage: import os
sage: from sage.dev.git_interface import GitInterface
sage: from sage.dev.test.config import DoctestConfig
sage: from sage.dev.test.user_interface import DoctestUserInterface
sage: config = DoctestConfig()
sage: git = GitInterface(config["git"], DoctestUserInterface(config["UI"]))
Create two conflicting branches:
sage: os.chdir(config['git']['src'])
sage: with open("file","w") as f: f.write("version 0")
sage: git.silent.add("file")
sage: git.silent.commit("-m","initial commit")
sage: git.super_silent.checkout("-b","branch1")
sage: with open("file","w") as f: f.write("version 1")
sage: git.silent.commit("-am","second commit")
sage: git.super_silent.checkout("master")
sage: git.super_silent.checkout("-b","branch2")
sage: with open("file","w") as f: f.write("version 2")
sage: git.silent.commit("-am","conflicting commit")
A merge state:
sage: git.super_silent.checkout("branch1")
sage: git.silent.merge('branch2')
Traceback (most recent call last):
...
GitError: git returned with non-zero exit code (1) for
"git -c user.email=doc@test.test -c user.name=doctest merge branch2".
...
sage: git.get_state()
('merge',)
sage: git.silent.merge(abort=True)
sage: git.get_state()
()
A rebase state:
sage: git._execute_supersilent('rebase', 'branch2')
Traceback (most recent call last):
...
GitError: git returned with non-zero exit code (1) for
"git -c user.email=doc@test.test -c user.name=doctest rebase branch2".
...
sage: git.get_state()
('rebase',)
sage: git.super_silent.rebase(abort=True)
sage: git.get_state()
()
Return whether there are uncommitted changes, i.e., whether there are modified files which are tracked by git.
EXAMPLES:
Create a GitInterface for doctesting:
sage: import os
sage: from sage.dev.git_interface import GitInterface
sage: from sage.dev.test.config import DoctestConfig
sage: from sage.dev.test.user_interface import DoctestUserInterface
sage: config = DoctestConfig()
sage: git = GitInterface(config["git"], DoctestUserInterface(config["UI"]))
An untracked file does not count towards uncommited changes:
sage: os.chdir(config['git']['src'])
sage: open('untracked','w').close()
sage: git.has_uncommitted_changes()
False
Once added to the index it does:
sage: git.silent.add('untracked')
sage: git.has_uncommitted_changes()
True
sage: git.silent.commit('-m', 'tracking untracked')
sage: git.has_uncommitted_changes()
False
sage: with open('untracked','w') as f: f.write('version 0')
sage: git.has_uncommitted_changes()
True
Return whether a is an ancestor of b.
EXAMPLES:
Create a GitInterface for doctesting:
sage: import os
sage: from sage.dev.git_interface import GitInterface
sage: from sage.dev.test.config import DoctestConfig
sage: from sage.dev.test.user_interface import DoctestUserInterface
sage: config = DoctestConfig()
sage: git = GitInterface(config["git"], DoctestUserInterface(config["UI"]))
Create two conflicting branches:
sage: os.chdir(config['git']['src'])
sage: with open("file","w") as f: f.write("version 0")
sage: git.silent.add("file")
sage: git.silent.commit("-m","initial commit")
sage: git.super_silent.checkout("-b","branch1")
sage: with open("file","w") as f: f.write("version 1")
sage: git.silent.commit("-am","second commit")
sage: git.super_silent.checkout("master")
sage: git.super_silent.checkout("-b","branch2")
sage: with open("file","w") as f: f.write("version 2")
sage: git.silent.commit("-am","conflicting commit")
sage: git.is_ancestor_of('master', 'branch2')
True
sage: git.is_ancestor_of('branch2', 'master')
False
sage: git.is_ancestor_of('branch1', 'branch2')
False
sage: git.is_ancestor_of('master', 'master')
True
Return whether a is a child of b.
EXAMPLES:
Create a GitInterface for doctesting:
sage: import os
sage: from sage.dev.git_interface import GitInterface
sage: from sage.dev.test.config import DoctestConfig
sage: from sage.dev.test.user_interface import DoctestUserInterface
sage: config = DoctestConfig()
sage: git = GitInterface(config["git"], DoctestUserInterface(config["UI"]))
Create two conflicting branches:
sage: os.chdir(config['git']['src'])
sage: with open("file","w") as f: f.write("version 0")
sage: git.silent.add("file")
sage: git.silent.commit("-m","initial commit")
sage: git.super_silent.checkout("-b","branch1")
sage: with open("file","w") as f: f.write("version 1")
sage: git.silent.commit("-am","second commit")
sage: git.super_silent.checkout("master")
sage: git.super_silent.checkout("-b","branch2")
sage: with open("file","w") as f: f.write("version 2")
sage: git.silent.commit("-am","conflicting commit")
sage: git.is_child_of('master', 'branch2')
False
sage: git.is_child_of('branch2', 'master')
True
sage: git.is_child_of('branch1', 'branch2')
False
sage: git.is_child_of('master', 'master')
True
Return a list of local branches sorted by last commit time.
EXAMPLES:
Create a GitInterface for doctesting:
sage: import os, time
sage: from sage.dev.git_interface import GitInterface
sage: from sage.dev.test.config import DoctestConfig
sage: from sage.dev.test.user_interface import DoctestUserInterface
sage: config = DoctestConfig()
sage: git = GitInterface(config["git"], DoctestUserInterface(config["UI"]))
Create some branches:
sage: os.chdir(config['git']['src'])
sage: env = {'GIT_COMMITTER_DATE': time.strftime("%Y-%m-%dT%H:%M:10")}
sage: git.silent.commit('-m','initial commit','--allow-empty', env=env)
sage: git.super_silent.checkout('-b', 'branch')
sage: env['GIT_COMMITTER_DATE'] = time.strftime("%Y-%m-%dT%H:%M:20")
sage: git.silent.commit('-m','second commit','--allow-empty', env=env)
sage: git.super_silent.checkout('-b', 'other', 'master')
sage: env['GIT_COMMITTER_DATE'] = time.strftime("%Y-%m-%dT%H:%M:30")
sage: git.silent.commit('-m','third commit','--allow-empty', env=env)
Use this repository as a remote repository:
sage: config2 = DoctestConfig()
sage: git2 = GitInterface(config2["git"], DoctestUserInterface(config["UI"]))
sage: os.chdir(config2['git']['src'])
sage: env['GIT_COMMITTER_DATE'] = time.strftime("%Y-%m-%dT%H:%M:40")
sage: git2.silent.commit('-m','initial commit','--allow-empty', env=env)
sage: git2.silent.remote('add', 'git', config['git']['src'])
sage: git2.super_silent.fetch('git')
sage: git2.super_silent.checkout("branch")
sage: git2.echo.branch("-a")
* branch
master
remotes/git/branch
remotes/git/master
remotes/git/other
sage: git2.local_branches()
['master', 'branch']
sage: os.chdir(config['git']['src'])
sage: git.local_branches()
['other', 'branch', 'master']
Rename oldname to newname.
EXAMPLES:
Create a GitInterface for doctesting:
sage: from sage.dev.git_interface import GitInterface
sage: from sage.dev.test.config import DoctestConfig
sage: from sage.dev.test.user_interface import DoctestUserInterface
sage: config = DoctestConfig()
sage: git = GitInterface(config["git"], DoctestUserInterface(config["UI"]))
Create some branches:
sage: os.chdir(config['git']['src'])
sage: git.silent.commit('-m','initial commit','--allow-empty')
sage: git.silent.branch('branch1')
sage: git.silent.branch('branch2')
Rename some branches:
sage: git.rename_branch('branch1', 'branch3')
sage: git.rename_branch('branch2', 'branch3')
Traceback (most recent call last):
...
GitError: git returned with non-zero exit code (128) for
"git -c user.email=doc@test.test -c user.name=doctest branch --move branch2 branch3".
output to stderr: fatal: A branch named 'branch3' already exists.
Get out of a merge/am/rebase/etc state.
EXAMPLES:
Create a GitInterface for doctesting:
sage: import os
sage: from sage.dev.git_interface import GitInterface
sage: from sage.dev.test.config import DoctestConfig
sage: from sage.dev.test.user_interface import DoctestUserInterface
sage: config = DoctestConfig()
sage: git = GitInterface(config["git"], DoctestUserInterface(config["UI"]))
Create two conflicting branches:
sage: os.chdir(config['git']['src'])
sage: with open("file","w") as f: f.write("version 0")
sage: git.silent.add("file")
sage: git.silent.commit("-m","initial commit")
sage: git.super_silent.checkout("-b","branch1")
sage: with open("file","w") as f: f.write("version 1")
sage: git.silent.commit("-am","second commit")
sage: git.super_silent.checkout("master")
sage: git.super_silent.checkout("-b","branch2")
sage: with open("file","w") as f: f.write("version 2")
sage: git.silent.commit("-am","conflicting commit")
A merge:
sage: git.silent.merge('branch1')
Traceback (most recent call last):
...
GitError: git returned with non-zero exit code (1) for
"git -c user.email=doc@test.test -c user.name=doctest merge branch1".
...
sage: git.get_state()
('merge',)
Get out of this state:
sage: git.reset_to_clean_state()
sage: git.get_state()
()
Return a list of file names for files that are not tracked by git and not ignored.
EXAMPLES:
Create a GitInterface for doctesting:
sage: import os
sage: from sage.dev.git_interface import GitInterface
sage: from sage.dev.test.config import DoctestConfig
sage: from sage.dev.test.user_interface import DoctestUserInterface
sage: config = DoctestConfig()
sage: git = GitInterface(config["git"], DoctestUserInterface(config["UI"]))
An untracked file:
sage: os.chdir(config['git']['src'])
sage: git.untracked_files()
[]
sage: open('untracked','w').close()
sage: git.untracked_files()
['untracked']
Directories are not displayed here::
sage: os.mkdir('untracked_dir')
sage: git.untracked_files()
['untracked']
sage: open('untracked_dir/untracked','w').close()
sage: git.untracked_files()
['untracked', 'untracked_dir/untracked']
Bases: object
A proxy object to wrap actual calls to git.
EXAMPLES:
sage: from sage.dev.git_interface import GitProxy
sage: from sage.dev.test.config import DoctestConfig
sage: from sage.dev.test.user_interface import DoctestUserInterface
sage: config = DoctestConfig()
sage: GitProxy(config['git'], DoctestUserInterface(config['UI']))
<sage.dev.git_interface.GitProxy object at 0x...>
Call git add.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.add() # not tested
Call git am.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.am() # not tested
Call git apply.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.apply() # not tested
Call git bisect.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.bisect() # not tested
Call git branch.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.branch() # not tested
Call git checkout.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.checkout() # not tested
Call git cherry-pick.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.cherry_pick() # not tested
Call git clean.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.clean() # not tested
Call git clone.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.clone() # not tested
Call git commit.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.commit() # not tested
Call git config.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.config() # not tested
Call git diff.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.diff() # not tested
Call git fetch.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.fetch() # not tested
Call git for-each-ref.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.for_each_ref() # not tested
Call git format-patch.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.format_patch() # not tested
Call git grep.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.grep() # not tested
Call git init.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.init() # not tested
Call git log.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.log() # not tested
Call git ls-files.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.ls_files() # not tested
Call git ls-remote.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.ls_remote() # not tested
Call git merge.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.merge() # not tested
Call git merge-base.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.merge_base() # not tested
Call git mv.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.mv() # not tested
Call git pull.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.pull() # not tested
Call git push.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.push() # not tested
Call git rebase.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.rebase() # not tested
Call git remote.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.remote() # not tested
Call git reset.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.reset() # not tested
Call git rev-list.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.rev_list() # not tested
Call git rev-parse.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.rev_parse() # not tested
Call git rm.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.rm() # not tested
Call git show.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.show() # not tested
Call git show-ref.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.show_ref() # not tested
Call git stash.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.stash() # not tested
Call git status.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.status() # not tested
Call git symbolic-ref.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.symbolic_ref() # not tested
Call git tag.
OUTPUT:
See the docstring of __call__ for more information.
EXAMPLES:
sage: dev.git.tag() # not tested
Bases: sage.dev.git_interface.GitProxy
A proxy object to wrap calls to git.
Calls to git return the stdout of git and raise an error on a non-zero exit code. Output to stderr is supressed.
EXAMPLES:
sage: dev.git.status() # not tested
Bases: sage.dev.git_interface.GitProxy
A proxy object to wrap calls to git.
Calls to git do not show any output to stdout and raise an error on a non-zero exit code. Output to stderr is printed.
EXAMPLES:
sage: dev.git.silent.status() # not tested
Bases: sage.dev.git_interface.GitProxy
A proxy object to wrap calls to git.
Calls to git do not show any output to stderr or stdout and raise an error on a non-zero exit code.
EXAMPLES:
sage: dev.git.super_silent.status() # not tested
Create a wrapper for git_cmd__.
EXAMPLES:
sage: import os
sage: from sage.dev.git_interface import GitInterface
sage: from sage.dev.test.config import DoctestConfig
sage: from sage.dev.test.user_interface import DoctestUserInterface
sage: config = DoctestConfig()
sage: git = GitInterface(config["git"], DoctestUserInterface(config["UI"]))
sage: os.chdir(config['git']['src'])
sage: git.echo.status() # indirect doctest
# On branch master
#
# Initial commit
#
nothing to commit (create/copy files and use "git add" to track)