Change git command
This commit is contained in:
1 parent
187a874094
commit
7128429d11
14 files changed
+175
-84
No files matched your search
@@ -30,6 +30,11 @@ config = [{
|
|||||||
'type': 'bool',
|
'type': 'bool',
|
||||||
'description': 'Automaticly update when update is available',
|
'description': 'Automaticly update when update is available',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'name': 'git_command',
|
||||||
|
'default': 'git',
|
||||||
|
'advanced': True
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ class Updater(Plugin):
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
self.repo = LocalRepository(Env.get('app_dir'))
|
self.repo = LocalRepository(Env.get('app_dir'), command = self.conf('git_command', default = 'git'))
|
||||||
|
|
||||||
fireEvent('schedule.interval', 'updater.check', self.check, hours = 6)
|
fireEvent('schedule.interval', 'updater.check', self.check, hours = 6)
|
||||||
|
|
||||||
|
|||||||
Regular → Executable
File mode changed.
Regular → Executable
+5
-5
@@ -31,8 +31,8 @@ class Branch(Ref):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<branch %s>" % (self.name,)
|
return "<branch %s>" % (self.name,)
|
||||||
class LocalBranch(Branch):
|
class LocalBranch(Branch):
|
||||||
def delete(self, force=True):
|
def delete(self, force = True):
|
||||||
self.repo._executeGitCommandAssertSuccess("git branch -%s %s" % ("D" if force else "d", self.name,))
|
self.repo._executeGitCommandAssertSuccess("branch -%s %s" % ("D" if force else "d", self.name,))
|
||||||
def setRemoteBranch(self, branch):
|
def setRemoteBranch(self, branch):
|
||||||
if branch is None:
|
if branch is None:
|
||||||
self.repo.config.unsetParameter('branch.%s.remote' % self.name)
|
self.repo.config.unsetParameter('branch.%s.remote' % self.name)
|
||||||
@@ -51,12 +51,12 @@ class LocalBranch(Branch):
|
|||||||
merge = re.sub('^refs/heads/', '', merge)
|
merge = re.sub('^refs/heads/', '', merge)
|
||||||
remote_branch = remote.getBranchByName(merge)
|
remote_branch = remote.getBranchByName(merge)
|
||||||
return remote_branch
|
return remote_branch
|
||||||
|
|
||||||
class LocalBranchAlias(LocalBranch):
|
class LocalBranchAlias(LocalBranch):
|
||||||
def __init__(self, repository, name, dest):
|
def __init__(self, repository, name, dest):
|
||||||
super(LocalBranchAlias, self).__init__(repository, name)
|
super(LocalBranchAlias, self).__init__(repository, name)
|
||||||
self.dest = dest
|
self.dest = dest
|
||||||
|
|
||||||
class RemoteBranch(Branch):
|
class RemoteBranch(Branch):
|
||||||
pass
|
pass
|
||||||
class RegisteredRemoteBranch(RemoteBranch):
|
class RegisteredRemoteBranch(RemoteBranch):
|
||||||
@@ -69,7 +69,7 @@ class RegisteredRemoteBranch(RemoteBranch):
|
|||||||
"""
|
"""
|
||||||
Deletes the actual branch on the remote repository!
|
Deletes the actual branch on the remote repository!
|
||||||
"""
|
"""
|
||||||
self.repo.push(self.remote, fromBranch="", toBranch=self, force=True)
|
self.repo.push(self.remote, fromBranch = "", toBranch = self, force = True)
|
||||||
def getNormalizedName(self):
|
def getNormalizedName(self):
|
||||||
return "%s/%s" % (self.remote.name, self.name)
|
return "%s/%s" % (self.remote.name, self.name)
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
|||||||
Regular → Executable
+3
-3
@@ -48,11 +48,11 @@ class Commit(Ref):
|
|||||||
raise TypeError("Comparing %s and %s" % (type(self), type(other)))
|
raise TypeError("Comparing %s and %s" % (type(self), type(other)))
|
||||||
return (self.hash == other.lower())
|
return (self.hash == other.lower())
|
||||||
def getParents(self):
|
def getParents(self):
|
||||||
output = self.repo._getOutputAssertSuccess("git rev-list %s --parents -1" % self)
|
output = self.repo._getOutputAssertSuccess("rev-list %s --parents -1" % self)
|
||||||
return [Commit(self.repo, sha.strip()) for sha in output.split()[1:]]
|
return [Commit(self.repo, sha.strip()) for sha in output.split()[1:]]
|
||||||
def getChange(self):
|
def getChange(self):
|
||||||
returned = []
|
returned = []
|
||||||
for line in self.repo._getOutputAssertSuccess("git show --pretty=format: --raw %s" % self).splitlines():
|
for line in self.repo._getOutputAssertSuccess("show --pretty=format: --raw %s" % self).splitlines():
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
if not line:
|
if not line:
|
||||||
continue
|
continue
|
||||||
@@ -62,7 +62,7 @@ class Commit(Ref):
|
|||||||
getChangedFiles = getChange
|
getChangedFiles = getChange
|
||||||
############################ Misc. Commit attributes ###########################
|
############################ Misc. Commit attributes ###########################
|
||||||
def _getCommitField(self, field):
|
def _getCommitField(self, field):
|
||||||
return self.repo._executeGitCommandAssertSuccess("git log -1 --pretty=format:%s %s" % (field, self)).stdout.read().strip()
|
return self.repo._executeGitCommandAssertSuccess("log -1 --pretty=format:%s %s" % (field, self)).stdout.read().strip()
|
||||||
def getAuthorName(self):
|
def getAuthorName(self):
|
||||||
return self._getCommitField("%an")
|
return self._getCommitField("%an")
|
||||||
def getAuthorEmail(self):
|
def getAuthorEmail(self):
|
||||||
|
|||||||
Regular → Executable
+6
-6
@@ -28,16 +28,16 @@ class GitConfiguration(object):
|
|||||||
def __init__(self, repo):
|
def __init__(self, repo):
|
||||||
super(GitConfiguration, self).__init__()
|
super(GitConfiguration, self).__init__()
|
||||||
self.repo = repo
|
self.repo = repo
|
||||||
def setParameter(self, path, value, local=True):
|
def setParameter(self, path, value, local = True):
|
||||||
self.repo._executeGitCommandAssertSuccess("git config %s \"%s\" \"%s\"" % ("" if local else "--global", path, value))
|
self.repo._executeGitCommandAssertSuccess("config %s \"%s\" \"%s\"" % ("" if local else "--global", path, value))
|
||||||
def unsetParameter(self, path, local=True):
|
def unsetParameter(self, path, local = True):
|
||||||
try:
|
try:
|
||||||
self.repo._executeGitCommandAssertSuccess("git config --unset %s \"%s\"" % ("" if local else "--global", path))
|
self.repo._executeGitCommandAssertSuccess("config --unset %s \"%s\"" % ("" if local else "--global", path))
|
||||||
except GitCommandFailedException:
|
except GitCommandFailedException:
|
||||||
if self.getParameter(path) is not None:
|
if self.getParameter(path) is not None:
|
||||||
raise
|
raise
|
||||||
def getParameter(self, path):
|
def getParameter(self, path):
|
||||||
return self.getDict().get(path, None)
|
return self.getDict().get(path, None)
|
||||||
def getDict(self):
|
def getDict(self):
|
||||||
return dict(line.strip().split("=",1)
|
return dict(line.strip().split("=", 1)
|
||||||
for line in self.repo._getOutputAssertSuccess("git config -l").splitlines())
|
for line in self.repo._getOutputAssertSuccess("config -l").splitlines())
|
||||||
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
+2
-2
@@ -31,9 +31,9 @@ class Ref(object):
|
|||||||
return self.repo._getCommitByRefName(self.name)
|
return self.repo._getCommitByRefName(self.name)
|
||||||
def getNormalizedName(self):
|
def getNormalizedName(self):
|
||||||
return self.name
|
return self.name
|
||||||
def getNewCommits(self, comparedTo, limit=""):
|
def getNewCommits(self, comparedTo, limit = ""):
|
||||||
returned = []
|
returned = []
|
||||||
command = "git cherry %s %s %s" % (self.repo._normalizeRefName(comparedTo),
|
command = "cherry %s %s %s" % (self.repo._normalizeRefName(comparedTo),
|
||||||
self.getNormalizedName(),
|
self.getNormalizedName(),
|
||||||
self.repo._normalizeRefName(limit))
|
self.repo._normalizeRefName(limit))
|
||||||
for line in self.repo._getOutputAssertSuccess(command).splitlines():
|
for line in self.repo._getOutputAssertSuccess(command).splitlines():
|
||||||
|
|||||||
Regular → Executable
File mode changed.
Regular → Executable
+4
-4
@@ -32,20 +32,20 @@ class Remote(ref_container.RefContainer):
|
|||||||
self.name = name
|
self.name = name
|
||||||
self.url = url
|
self.url = url
|
||||||
def fetch(self):
|
def fetch(self):
|
||||||
self.repo._executeGitCommandAssertSuccess("git fetch %s" % self.name)
|
self.repo._executeGitCommandAssertSuccess("fetch %s" % self.name)
|
||||||
def prune(self):
|
def prune(self):
|
||||||
self.repo._executeGitCommandAssertSuccess("git remote prune %s" % self.name)
|
self.repo._executeGitCommandAssertSuccess("remote prune %s" % self.name)
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return (type(self) is type(other)) and (self.name == other.name)
|
return (type(self) is type(other)) and (self.name == other.name)
|
||||||
###################### For compatibility with RefContainer #####################
|
###################### For compatibility with RefContainer #####################
|
||||||
def getBranches(self):
|
def getBranches(self):
|
||||||
prefix = "%s/" % self.name
|
prefix = "%s/" % self.name
|
||||||
returned = []
|
returned = []
|
||||||
for line in self.repo._getOutputAssertSuccess("git branch -r").splitlines():
|
for line in self.repo._getOutputAssertSuccess("branch -r").splitlines():
|
||||||
if self.repo.getGitVersion() >= '1.6.3' and ' -> ' in line:
|
if self.repo.getGitVersion() >= '1.6.3' and ' -> ' in line:
|
||||||
continue
|
continue
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
if line.startswith(prefix):
|
if line.startswith(prefix):
|
||||||
returned.append(branch.RegisteredRemoteBranch(self.repo, self, line[len(prefix):]))
|
returned.append(branch.RegisteredRemoteBranch(self.repo, self, line[len(prefix):]))
|
||||||
return returned
|
return returned
|
||||||
|
|
||||||
Regular → Executable
+116
-63
@@ -22,12 +22,14 @@
|
|||||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
# 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
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
from collections import Sequence
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from . import branch
|
from . import branch
|
||||||
|
from . import tag
|
||||||
from . import commit
|
from . import commit
|
||||||
from . import config
|
from . import config
|
||||||
from .files import ModifiedFile
|
from .files import ModifiedFile
|
||||||
@@ -42,10 +44,16 @@ from .exceptions import CannotFindRepository
|
|||||||
from .exceptions import GitException
|
from .exceptions import GitException
|
||||||
from .exceptions import GitCommandFailedException
|
from .exceptions import GitCommandFailedException
|
||||||
from .exceptions import MergeConflict
|
from .exceptions import MergeConflict
|
||||||
|
from .exceptions import NonexistentRefException
|
||||||
|
|
||||||
BRANCH_ALIAS_MARKER = ' -> '
|
BRANCH_ALIAS_MARKER = ' -> '
|
||||||
|
|
||||||
class Repository(ref_container.RefContainer):
|
class Repository(ref_container.RefContainer):
|
||||||
|
|
||||||
|
_git_command = None
|
||||||
|
def setCommand(self, command):
|
||||||
|
self._git_command = command
|
||||||
|
|
||||||
############################# internal methods #############################
|
############################# internal methods #############################
|
||||||
_loggingEnabled = False
|
_loggingEnabled = False
|
||||||
def _getWorkingDirectory(self):
|
def _getWorkingDirectory(self):
|
||||||
@@ -57,16 +65,17 @@ class Repository(ref_container.RefContainer):
|
|||||||
self._loggingEnabled = True
|
self._loggingEnabled = True
|
||||||
def disableLogging(self):
|
def disableLogging(self):
|
||||||
self._loggingEnabled = False
|
self._loggingEnabled = False
|
||||||
def _executeGitCommand(self, command, cwd=None):
|
def _executeGitCommand(self, command, cwd = None):
|
||||||
if cwd is None:
|
if cwd is None:
|
||||||
cwd = self._getWorkingDirectory()
|
cwd = self._getWorkingDirectory()
|
||||||
command = str(command)
|
command = '%s %s' % (self._git_command, str(command))
|
||||||
|
|
||||||
self._logGitCommand(command, cwd)
|
self._logGitCommand(command, cwd)
|
||||||
returned = subprocess.Popen(command,
|
returned = subprocess.Popen(command,
|
||||||
shell=True,
|
shell = True,
|
||||||
cwd=cwd,
|
cwd = cwd,
|
||||||
stdout=subprocess.PIPE,
|
stdout = subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE)
|
stderr = subprocess.PIPE)
|
||||||
returned.wait()
|
returned.wait()
|
||||||
return returned
|
return returned
|
||||||
def _executeGitCommandAssertSuccess(self, command, **kwargs):
|
def _executeGitCommandAssertSuccess(self, command, **kwargs):
|
||||||
@@ -90,22 +99,34 @@ class Repository(ref_container.RefContainer):
|
|||||||
|
|
||||||
############################## remote repositories #############################
|
############################## remote repositories #############################
|
||||||
class RemoteRepository(Repository):
|
class RemoteRepository(Repository):
|
||||||
def __init__(self, url):
|
def __init__(self, url, command = 'git'):
|
||||||
|
self.setCommand(command)
|
||||||
super(RemoteRepository, self).__init__()
|
super(RemoteRepository, self).__init__()
|
||||||
self.url = url
|
self.url = url
|
||||||
def _getRefs(self, prefix):
|
def _getRefs(self, prefix = ''):
|
||||||
output = self._executeGitCommandAssertSuccess("git ls-remote %s" % (self.url,))
|
output = self._executeGitCommandAssertSuccess("ls-remote %s" % (self.url,))
|
||||||
for output_line in output.stdout:
|
for output_line in output.stdout:
|
||||||
commit, refname = output_line.split()
|
commit, refname = output_line.split()
|
||||||
if refname.startswith(prefix):
|
if refname.startswith(prefix):
|
||||||
yield refname[len(prefix):]
|
yield refname[len(prefix):], commit.strip()
|
||||||
def _getRefsAsClass(self, prefix, cls):
|
def _getRefsAsClass(self, prefix, cls):
|
||||||
return [cls(self, ref) for ref in self._getRefs(prefix)]
|
return [cls(self, ref) for ref, _ in self._getRefs(prefix)]
|
||||||
|
def _getCommitByRefName(self, refname):
|
||||||
|
sha_by_ref = dict(self._getRefs())
|
||||||
|
for prefix in 'refs/tags/', 'refs/heads/':
|
||||||
|
sha = sha_by_ref.get(prefix + refname, None)
|
||||||
|
if sha is not None:
|
||||||
|
return commit.Commit(self, sha)
|
||||||
|
raise NonexistentRefException("Cannot find ref name %r in %s" % (refname, self))
|
||||||
|
|
||||||
def getBranches(self):
|
def getBranches(self):
|
||||||
return self._getRefsAsClass('refs/heads/', branch.RemoteBranch)
|
return self._getRefsAsClass('refs/heads/', branch.RemoteBranch)
|
||||||
|
def getTags(self):
|
||||||
|
return self._getRefsAsClass('refs/tags/', tag.RemoteTag)
|
||||||
############################## local repositories ##############################
|
############################## local repositories ##############################
|
||||||
class LocalRepository(Repository):
|
class LocalRepository(Repository):
|
||||||
def __init__(self, path):
|
def __init__(self, path, command = 'git'):
|
||||||
|
self.setCommand(command)
|
||||||
super(LocalRepository, self).__init__()
|
super(LocalRepository, self).__init__()
|
||||||
self.path = path
|
self.path = path
|
||||||
self.config = config.GitConfiguration(self)
|
self.config = config.GitConfiguration(self)
|
||||||
@@ -117,25 +138,25 @@ class LocalRepository(Repository):
|
|||||||
def _getCommitByHash(self, sha):
|
def _getCommitByHash(self, sha):
|
||||||
return commit.Commit(self, sha)
|
return commit.Commit(self, sha)
|
||||||
def _getCommitByRefName(self, name):
|
def _getCommitByRefName(self, name):
|
||||||
return commit.Commit(self, self._getOutputAssertSuccess("git rev-parse %s" % name).strip())
|
return commit.Commit(self, self._getOutputAssertSuccess("rev-parse %s" % name).strip())
|
||||||
def _getCommitByPartialHash(self, sha):
|
def _getCommitByPartialHash(self, sha):
|
||||||
return self._getCommitByRefName(sha)
|
return self._getCommitByRefName(sha)
|
||||||
def getGitVersion(self):
|
def getGitVersion(self):
|
||||||
if self._version is None:
|
if self._version is None:
|
||||||
version_output = self._getOutputAssertSuccess("git version")
|
version_output = self._getOutputAssertSuccess("version")
|
||||||
version_match = re.match(r"git\s+version\s+(\S+)$", version_output, re.I)
|
version_match = re.match(r"git\s+version\s+(\S+)$", version_output, re.I)
|
||||||
if version_match is None:
|
if version_match is None:
|
||||||
raise GitException("Cannot extract git version (unfamiliar output format %r?)" % version_output)
|
raise GitException("Cannot extract git version (unfamiliar output format %r?)" % version_output)
|
||||||
self._version = version_match.group(1)
|
self._version = version_match.group(1)
|
||||||
return self._version
|
return self._version
|
||||||
########################### Initializing a repository ##########################
|
########################### Initializing a repository ##########################
|
||||||
def init(self, bare=False):
|
def init(self, bare = False):
|
||||||
if not os.path.exists(self.path):
|
if not os.path.exists(self.path):
|
||||||
os.mkdir(self.path)
|
os.mkdir(self.path)
|
||||||
if not os.path.isdir(self.path):
|
if not os.path.isdir(self.path):
|
||||||
raise GitException("Cannot create repository in %s - "
|
raise GitException("Cannot create repository in %s - "
|
||||||
"not a directory" % self.path)
|
"not a directory" % self.path)
|
||||||
self._executeGitCommandAssertSuccess("git init %s" % ("--bare" if bare else ""))
|
self._executeGitCommandAssertSuccess("init %s" % ("--bare" if bare else ""))
|
||||||
def _asURL(self, repo):
|
def _asURL(self, repo):
|
||||||
if isinstance(repo, LocalRepository):
|
if isinstance(repo, LocalRepository):
|
||||||
repo = repo.path
|
repo = repo.path
|
||||||
@@ -145,11 +166,11 @@ class LocalRepository(Repository):
|
|||||||
raise TypeError("Cannot clone from %r" % (repo,))
|
raise TypeError("Cannot clone from %r" % (repo,))
|
||||||
return repo
|
return repo
|
||||||
def clone(self, repo):
|
def clone(self, repo):
|
||||||
self._executeGitCommandAssertSuccess("git clone %s %s" % (self._asURL(repo), self.path), cwd=".")
|
self._executeGitCommandAssertSuccess("clone %s %s" % (self._asURL(repo), self.path), cwd = ".")
|
||||||
########################### Querying repository refs ###########################
|
########################### Querying repository refs ###########################
|
||||||
def getBranches(self):
|
def getBranches(self):
|
||||||
returned = []
|
returned = []
|
||||||
for git_branch_line in self._executeGitCommandAssertSuccess("git branch").stdout:
|
for git_branch_line in self._executeGitCommandAssertSuccess("branch").stdout:
|
||||||
if git_branch_line.startswith("*"):
|
if git_branch_line.startswith("*"):
|
||||||
git_branch_line = git_branch_line[1:]
|
git_branch_line = git_branch_line[1:]
|
||||||
git_branch_line = git_branch_line.strip()
|
git_branch_line = git_branch_line.strip()
|
||||||
@@ -159,20 +180,25 @@ class LocalRepository(Repository):
|
|||||||
else:
|
else:
|
||||||
returned.append(branch.LocalBranch(self, git_branch_line))
|
returned.append(branch.LocalBranch(self, git_branch_line))
|
||||||
return returned
|
return returned
|
||||||
|
def getTags(self):
|
||||||
|
returned = []
|
||||||
|
for git_tag_line in self._executeGitCommandAssertSuccess("tag").stdout:
|
||||||
|
returned.append(tag.LocalTag(self, git_tag_line.strip()))
|
||||||
|
return returned
|
||||||
def _getCommits(self, specs, includeMerges):
|
def _getCommits(self, specs, includeMerges):
|
||||||
command = "git log --pretty=format:%%H %s" % specs
|
command = "log --pretty=format:%%H %s" % specs
|
||||||
if not includeMerges:
|
if not includeMerges:
|
||||||
command += " --no-merges"
|
command += " --no-merges"
|
||||||
for c in self._executeGitCommandAssertSuccess(command).stdout:
|
for c in self._executeGitCommandAssertSuccess(command).stdout:
|
||||||
yield commit.Commit(self, c.strip())
|
yield commit.Commit(self, c.strip())
|
||||||
def getCommits(self, start=None, end="HEAD", includeMerges=True):
|
def getCommits(self, start = None, end = "HEAD", includeMerges = True):
|
||||||
spec = self._normalizeRefName(start or "")
|
spec = self._normalizeRefName(start or "")
|
||||||
spec += ".."
|
spec += ".."
|
||||||
spec += self._normalizeRefName(end)
|
spec += self._normalizeRefName(end)
|
||||||
return list(self._getCommits(spec, includeMerges=includeMerges))
|
return list(self._getCommits(spec, includeMerges = includeMerges))
|
||||||
def getCurrentBranch(self):
|
def getCurrentBranch(self):
|
||||||
#todo: improve this method of obtaining current branch
|
#todo: improve this method of obtaining current branch
|
||||||
for branch_name in self._executeGitCommandAssertSuccess("git branch").stdout:
|
for branch_name in self._executeGitCommandAssertSuccess("branch").stdout:
|
||||||
branch_name = branch_name.strip()
|
branch_name = branch_name.strip()
|
||||||
if not branch_name.startswith("*"):
|
if not branch_name.startswith("*"):
|
||||||
continue
|
continue
|
||||||
@@ -183,7 +209,7 @@ class LocalRepository(Repository):
|
|||||||
def getRemotes(self):
|
def getRemotes(self):
|
||||||
config_dict = self.config.getDict()
|
config_dict = self.config.getDict()
|
||||||
returned = []
|
returned = []
|
||||||
for line in self._getOutputAssertSuccess("git remote show -n").splitlines():
|
for line in self._getOutputAssertSuccess("remote show -n").splitlines():
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
returned.append(remotes.Remote(self, line, config_dict.get('remote.%s.url' % line.strip())))
|
returned.append(remotes.Remote(self, line, config_dict.get('remote.%s.url' % line.strip())))
|
||||||
return returned
|
return returned
|
||||||
@@ -194,16 +220,16 @@ class LocalRepository(Repository):
|
|||||||
a = a.getHead()
|
a = a.getHead()
|
||||||
if isinstance(b, ref.Ref):
|
if isinstance(b, ref.Ref):
|
||||||
b = b.getHead()
|
b = b.getHead()
|
||||||
returned = self._executeGitCommand("git merge-base %s %s" % (a, b))
|
returned = self._executeGitCommand("merge-base %s %s" % (a, b))
|
||||||
if returned.returncode == 0:
|
if returned.returncode == 0:
|
||||||
return commit.Commit(self, returned.stdout.read().strip())
|
return commit.Commit(self, returned.stdout.read().strip())
|
||||||
# make sure this is not a misc. error with git
|
# make sure this is not a misc. error with git
|
||||||
unused = self.getHead()
|
unused = self.getHead()
|
||||||
return None
|
return None
|
||||||
################################ Querying Status ###############################
|
################################ Querying Status ###############################
|
||||||
def containsCommit(self, commit):
|
def containsCommit(self, commit):
|
||||||
try:
|
try:
|
||||||
self._executeGitCommandAssertSuccess("git log -1 %s" % (commit,))
|
self._executeGitCommandAssertSuccess("log -1 %s" % (commit,))
|
||||||
except GitException:
|
except GitException:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
@@ -212,11 +238,24 @@ class LocalRepository(Repository):
|
|||||||
def _getFiles(self, *flags):
|
def _getFiles(self, *flags):
|
||||||
flags = ["--exclude-standard"] + list(flags)
|
flags = ["--exclude-standard"] + list(flags)
|
||||||
return [f.strip()
|
return [f.strip()
|
||||||
for f in self._getOutputAssertSuccess("git ls-files %s" % (" ".join(flags))).splitlines()]
|
for f in self._getOutputAssertSuccess("ls-files %s" % (" ".join(flags))).splitlines()]
|
||||||
def _getRawDiff(self, *flags):
|
def _getRawDiff(self, *flags, **options):
|
||||||
|
match_statuses = options.pop('fileStatuses', None)
|
||||||
|
if match_statuses is not None and not isinstance(match_statuses, Sequence):
|
||||||
|
raise ValueError("matchedStatuses must be a sequence")
|
||||||
|
if options:
|
||||||
|
raise TypeError("Unknown arguments specified: %s" % ", ".join(options))
|
||||||
|
|
||||||
flags = " ".join(str(f) for f in flags)
|
flags = " ".join(str(f) for f in flags)
|
||||||
return [ModifiedFile(line.split()[-1]) for line in
|
modified_files = []
|
||||||
self._getOutputAssertSuccess("git diff --raw %s" % flags).splitlines()]
|
for line in self._getOutputAssertSuccess("diff --raw %s" % flags).splitlines():
|
||||||
|
file_status = line.split()[-2]
|
||||||
|
file_name = line.split()[-1]
|
||||||
|
if match_statuses is None or file_status in match_statuses:
|
||||||
|
modified_files.append(ModifiedFile(file_name))
|
||||||
|
|
||||||
|
return modified_files
|
||||||
|
|
||||||
def getStagedFiles(self):
|
def getStagedFiles(self):
|
||||||
if self.isInitialized():
|
if self.isInitialized():
|
||||||
return self._getRawDiff('--cached')
|
return self._getRawDiff('--cached')
|
||||||
@@ -225,6 +264,8 @@ class LocalRepository(Repository):
|
|||||||
return self._getFiles()
|
return self._getFiles()
|
||||||
def getChangedFiles(self):
|
def getChangedFiles(self):
|
||||||
return self._getRawDiff()
|
return self._getRawDiff()
|
||||||
|
def getDeletedFiles(self):
|
||||||
|
return self._getRawDiff(fileStatuses = ['D'])
|
||||||
def getUntrackedFiles(self):
|
def getUntrackedFiles(self):
|
||||||
return self._getFiles("--others")
|
return self._getFiles("--others")
|
||||||
def isInitialized(self):
|
def isInitialized(self):
|
||||||
@@ -244,7 +285,14 @@ class LocalRepository(Repository):
|
|||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
################################ Staging content ###############################
|
################################ Staging content ###############################
|
||||||
def add(self, path):
|
def add(self, path):
|
||||||
self._executeGitCommandAssertSuccess("git add %s" % quote_for_shell(path))
|
self._executeGitCommandAssertSuccess("add %s" % quote_for_shell(path))
|
||||||
|
def delete(self, path, recursive = False, force = False):
|
||||||
|
flags = ""
|
||||||
|
if recursive:
|
||||||
|
flags += "-r "
|
||||||
|
if force:
|
||||||
|
flags += "-f "
|
||||||
|
self._executeGitCommandAssertSuccess("rm %s%s" % (flags, quote_for_shell(path)))
|
||||||
def addAll(self):
|
def addAll(self):
|
||||||
return self.add('.')
|
return self.add('.')
|
||||||
################################## Committing ##################################
|
################################## Committing ##################################
|
||||||
@@ -261,31 +309,38 @@ class LocalRepository(Repository):
|
|||||||
if match:
|
if match:
|
||||||
return commit.Commit(self, match.group(1))
|
return commit.Commit(self, match.group(1))
|
||||||
return None
|
return None
|
||||||
def commit(self, message, allowEmpty=False):
|
def commit(self, message, allowEmpty = False, commitAll = False):
|
||||||
command = "git commit -m %s" % quote_for_shell(message)
|
args = ''
|
||||||
|
if commitAll:
|
||||||
|
args = args + '--all'
|
||||||
|
command = "commit %s -m %s" % (args, quote_for_shell(message))
|
||||||
if allowEmpty:
|
if allowEmpty:
|
||||||
command += " --allow-empty"
|
command += " --allow-empty"
|
||||||
output = self._getOutputAssertSuccess(command)
|
output = self._getOutputAssertSuccess(command)
|
||||||
return self._deduceNewCommitFromCommitOutput(output)
|
return self._deduceNewCommitFromCommitOutput(output)
|
||||||
################################ Changing state ################################
|
################################ Changing state ################################
|
||||||
def createBranch(self, name, startingPoint=None):
|
def _createBranchOrTag(self, objname, name, startingPoint, returned_class):
|
||||||
command = "git branch %s " % name
|
command = "%s %s " % (objname, name)
|
||||||
if startingPoint is not None:
|
if startingPoint is not None:
|
||||||
command += self._normalizeRefName(startingPoint)
|
command += self._normalizeRefName(startingPoint)
|
||||||
self._executeGitCommandAssertSuccess(command)
|
self._executeGitCommandAssertSuccess(command)
|
||||||
return branch.LocalBranch(self, name)
|
return returned_class(self, name)
|
||||||
def checkout(self, thing=None, targetBranch=None, files=()):
|
def createBranch(self, name, startingPoint = None):
|
||||||
|
return self._createBranchOrTag('branch', name, startingPoint, branch.LocalBranch)
|
||||||
|
def createTag(self, name, startingPoint = None):
|
||||||
|
return self._createBranchOrTag('tag', name, startingPoint, tag.LocalTag)
|
||||||
|
def checkout(self, thing = None, targetBranch = None, files = ()):
|
||||||
if thing is None:
|
if thing is None:
|
||||||
thing = ""
|
thing = ""
|
||||||
command = "git checkout %s" % (self._normalizeRefName(thing),)
|
command = "checkout %s" % (self._normalizeRefName(thing),)
|
||||||
if targetBranch is not None:
|
if targetBranch is not None:
|
||||||
command += " -b %s" % (targetBranch,)
|
command += " -b %s" % (targetBranch,)
|
||||||
if files:
|
if files:
|
||||||
command += " -- %s" % " ".join(files)
|
command += " -- %s" % " ".join(files)
|
||||||
self._executeGitCommandAssertSuccess(command)
|
self._executeGitCommandAssertSuccess(command)
|
||||||
def mergeMultiple(self, srcs, allowFastForward=True, log=False, message=None):
|
def mergeMultiple(self, srcs, allowFastForward = True, log = False, message = None):
|
||||||
try:
|
try:
|
||||||
self._executeGitCommandAssertSuccess(CMD("git merge",
|
self._executeGitCommandAssertSuccess(CMD("merge",
|
||||||
" ".join(self._normalizeRefName(src) for src in srcs),
|
" ".join(self._normalizeRefName(src) for src in srcs),
|
||||||
"--no-ff" if not allowFastForward else None,
|
"--no-ff" if not allowFastForward else None,
|
||||||
"--log" if log else None,
|
"--log" if log else None,
|
||||||
@@ -299,18 +354,18 @@ class LocalRepository(Repository):
|
|||||||
def merge(self, src, *args, **kwargs):
|
def merge(self, src, *args, **kwargs):
|
||||||
return self.mergeMultiple([src], *args, **kwargs)
|
return self.mergeMultiple([src], *args, **kwargs)
|
||||||
def _reset(self, flag, thing):
|
def _reset(self, flag, thing):
|
||||||
command = "git reset %s %s" % (
|
command = "reset %s %s" % (
|
||||||
flag,
|
flag,
|
||||||
self._normalizeRefName(thing))
|
self._normalizeRefName(thing))
|
||||||
self._executeGitCommandAssertSuccess(command)
|
self._executeGitCommandAssertSuccess(command)
|
||||||
def resetSoft(self, thing="HEAD"):
|
def resetSoft(self, thing = "HEAD"):
|
||||||
return self._reset("--soft", thing)
|
return self._reset("--soft", thing)
|
||||||
def resetHard(self, thing="HEAD"):
|
def resetHard(self, thing = "HEAD"):
|
||||||
return self._reset("--hard", thing)
|
return self._reset("--hard", thing)
|
||||||
def resetMixed(self, thing="HEAD"):
|
def resetMixed(self, thing = "HEAD"):
|
||||||
return self._reset("--mixed", thing)
|
return self._reset("--mixed", thing)
|
||||||
def _clean(self, flags):
|
def _clean(self, flags):
|
||||||
self._executeGitCommandAssertSuccess("git clean -q " + flags)
|
self._executeGitCommandAssertSuccess("clean -q " + flags)
|
||||||
def cleanIgnoredFiles(self):
|
def cleanIgnoredFiles(self):
|
||||||
"""Cleans files that match the patterns in .gitignore"""
|
"""Cleans files that match the patterns in .gitignore"""
|
||||||
return self._clean("-f -X")
|
return self._clean("-f -X")
|
||||||
@@ -318,21 +373,21 @@ class LocalRepository(Repository):
|
|||||||
return self._clean("-f -d")
|
return self._clean("-f -d")
|
||||||
################################# collaboration ################################
|
################################# collaboration ################################
|
||||||
def addRemote(self, name, url):
|
def addRemote(self, name, url):
|
||||||
self._executeGitCommandAssertSuccess("git remote add %s %s" % (name, url))
|
self._executeGitCommandAssertSuccess("remote add %s %s" % (name, url))
|
||||||
return remotes.Remote(self, name, url)
|
return remotes.Remote(self, name, url)
|
||||||
def fetch(self, repo=None):
|
def fetch(self, repo = None):
|
||||||
command = "git fetch"
|
command = "fetch"
|
||||||
if repo is not None:
|
if repo is not None:
|
||||||
command += " "
|
command += " "
|
||||||
command += self._asURL(repo)
|
command += self._asURL(repo)
|
||||||
self._executeGitCommandAssertSuccess(command)
|
self._executeGitCommandAssertSuccess(command)
|
||||||
def pull(self, repo=None):
|
def pull(self, repo = None):
|
||||||
command = "git pull"
|
command = "pull"
|
||||||
if repo is not None:
|
if repo is not None:
|
||||||
command += " "
|
command += " "
|
||||||
command += self._asURL(repo)
|
command += self._asURL(repo)
|
||||||
self._executeGitCommandAssertSuccess(command)
|
self._executeGitCommandAssertSuccess(command)
|
||||||
def _getRefspec(self, fromBranch=None, toBranch=None, force=False):
|
def _getRefspec(self, fromBranch = None, toBranch = None, force = False):
|
||||||
returned = ""
|
returned = ""
|
||||||
if fromBranch is not None:
|
if fromBranch is not None:
|
||||||
returned += self._normalizeRefName(fromBranch)
|
returned += self._normalizeRefName(fromBranch)
|
||||||
@@ -345,10 +400,10 @@ class LocalRepository(Repository):
|
|||||||
if returned and force:
|
if returned and force:
|
||||||
returned = "+%s" % returned
|
returned = "+%s" % returned
|
||||||
return returned
|
return returned
|
||||||
def push(self, remote=None, fromBranch=None, toBranch=None, force=False):
|
def push(self, remote = None, fromBranch = None, toBranch = None, force = False):
|
||||||
command = "git push"
|
command = "push"
|
||||||
#build push arguments
|
#build push arguments
|
||||||
refspec = self._getRefspec(toBranch=toBranch, fromBranch=fromBranch, force=force)
|
refspec = self._getRefspec(toBranch = toBranch, fromBranch = fromBranch, force = force)
|
||||||
|
|
||||||
if refspec and not remote:
|
if refspec and not remote:
|
||||||
remote = "origin"
|
remote = "origin"
|
||||||
@@ -360,24 +415,22 @@ class LocalRepository(Repository):
|
|||||||
remote = remote.path
|
remote = remote.path
|
||||||
if remote is not None and not isinstance(remote, basestring):
|
if remote is not None and not isinstance(remote, basestring):
|
||||||
raise TypeError("Invalid type for 'remote' parameter: %s" % (type(remote),))
|
raise TypeError("Invalid type for 'remote' parameter: %s" % (type(remote),))
|
||||||
command = "git push %s %s" % (remote if remote is not None else "", refspec)
|
command = "push %s %s" % (remote if remote is not None else "", refspec)
|
||||||
self._executeGitCommandAssertSuccess(command)
|
self._executeGitCommandAssertSuccess(command)
|
||||||
def rebase(self, src):
|
def rebase(self, src):
|
||||||
self._executeGitCommandAssertSuccess("git rebase %s" % self._normalizeRefName(src))
|
self._executeGitCommandAssertSuccess("rebase %s" % self._normalizeRefName(src))
|
||||||
#################################### Stashes ###################################
|
#################################### Stashes ###################################
|
||||||
def saveStash(self, name=None):
|
def saveStash(self, name = None):
|
||||||
command = "git stash save"
|
command = "stash save"
|
||||||
if name is not None:
|
if name is not None:
|
||||||
command += " %s" % name
|
command += " %s" % name
|
||||||
self._executeGitCommandAssertSuccess(command)
|
self._executeGitCommandAssertSuccess(command)
|
||||||
def popStash(self, arg=None):
|
def popStash(self, arg = None):
|
||||||
command = "git stash pop"
|
command = "stash pop"
|
||||||
if arg is not None:
|
if arg is not None:
|
||||||
command += " %s" % arg
|
command += " %s" % arg
|
||||||
self._executeGitCommandAssertSuccess(command)
|
self._executeGitCommandAssertSuccess(command)
|
||||||
################################# Configuration ################################
|
################################# Configuration ################################
|
||||||
def getConfig(self):
|
|
||||||
return dict(s.split("=",1) for s in self._getOutputAssertSuccess("git config -l"))
|
|
||||||
|
|
||||||
################################### Shortcuts ##################################
|
################################### Shortcuts ##################################
|
||||||
def clone(source, location):
|
def clone(source, location):
|
||||||
@@ -396,4 +449,4 @@ def find_repository():
|
|||||||
path, path_tail = os.path.split(current_path)
|
path, path_tail = os.path.split(current_path)
|
||||||
if not path_tail:
|
if not path_tail:
|
||||||
raise CannotFindRepository("Cannot find repository for %s" % (orig_path,))
|
raise CannotFindRepository("Cannot find repository for %s" % (orig_path,))
|
||||||
|
|
||||||
Executable
+33
@@ -0,0 +1,33 @@
|
|||||||
|
# Copyright (c) 2009, Rotem Yaari <vmalloc@gmail.com>
|
||||||
|
# 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 organization 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 Rotem Yaari ''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 Rotem Yaari 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.
|
||||||
|
from ref import Ref
|
||||||
|
|
||||||
|
class Tag(Ref):
|
||||||
|
def __repr__(self):
|
||||||
|
return "<tag %s>" % (self.name,)
|
||||||
|
class LocalTag(Tag):
|
||||||
|
pass
|
||||||
|
class RemoteTag(Tag):
|
||||||
|
pass
|
||||||
Regular → Executable
File mode changed.
Reference in new issue
Block a user