Browse Source

Change git command

pull/66/head
Ruud 14 years ago
parent
commit
7128429d11
  1. 5
      couchpotato/core/plugins/updater/__init__.py
  2. 2
      couchpotato/core/plugins/updater/main.py
  3. 0
      libs/git/__init__.py
  4. 2
      libs/git/branch.py
  5. 6
      libs/git/commit.py
  6. 6
      libs/git/config.py
  7. 0
      libs/git/exceptions.py
  8. 0
      libs/git/files.py
  9. 2
      libs/git/ref.py
  10. 0
      libs/git/ref_container.py
  11. 6
      libs/git/remotes.py
  12. 135
      libs/git/repository.py
  13. 33
      libs/git/tag.py
  14. 0
      libs/git/utils.py

5
couchpotato/core/plugins/updater/__init__.py

@ -30,6 +30,11 @@ config = [{
'type': 'bool',
'description': 'Automaticly update when update is available',
},
{
'name': 'git_command',
'default': 'git',
'advanced': True
},
],
},
],

2
couchpotato/core/plugins/updater/main.py

@ -24,7 +24,7 @@ class Updater(Plugin):
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)

0
libs/git/__init__.py

2
libs/git/branch.py

@ -32,7 +32,7 @@ class Branch(Ref):
return "<branch %s>" % (self.name,)
class LocalBranch(Branch):
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):
if branch is None:
self.repo.config.unsetParameter('branch.%s.remote' % self.name)

6
libs/git/commit.py

@ -48,11 +48,11 @@ class Commit(Ref):
raise TypeError("Comparing %s and %s" % (type(self), type(other)))
return (self.hash == other.lower())
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:]]
def getChange(self):
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()
if not line:
continue
@ -62,7 +62,7 @@ class Commit(Ref):
getChangedFiles = getChange
############################ Misc. Commit attributes ###########################
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):
return self._getCommitField("%an")
def getAuthorEmail(self):

6
libs/git/config.py

@ -29,10 +29,10 @@ class GitConfiguration(object):
super(GitConfiguration, self).__init__()
self.repo = repo
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):
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:
if self.getParameter(path) is not None:
raise
@ -40,4 +40,4 @@ class GitConfiguration(object):
return self.getDict().get(path, None)
def getDict(self):
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())

0
libs/git/exceptions.py

0
libs/git/files.py

2
libs/git/ref.py

@ -33,7 +33,7 @@ class Ref(object):
return self.name
def getNewCommits(self, comparedTo, limit = ""):
returned = []
command = "git cherry %s %s %s" % (self.repo._normalizeRefName(comparedTo),
command = "cherry %s %s %s" % (self.repo._normalizeRefName(comparedTo),
self.getNormalizedName(),
self.repo._normalizeRefName(limit))
for line in self.repo._getOutputAssertSuccess(command).splitlines():

0
libs/git/ref_container.py

6
libs/git/remotes.py

@ -32,16 +32,16 @@ class Remote(ref_container.RefContainer):
self.name = name
self.url = url
def fetch(self):
self.repo._executeGitCommandAssertSuccess("git fetch %s" % self.name)
self.repo._executeGitCommandAssertSuccess("fetch %s" % self.name)
def prune(self):
self.repo._executeGitCommandAssertSuccess("git remote prune %s" % self.name)
self.repo._executeGitCommandAssertSuccess("remote prune %s" % self.name)
def __eq__(self, other):
return (type(self) is type(other)) and (self.name == other.name)
###################### For compatibility with RefContainer #####################
def getBranches(self):
prefix = "%s/" % self.name
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:
continue
line = line.strip()

135
libs/git/repository.py

@ -22,12 +22,14 @@
# 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 collections import Sequence
import re
import os
import subprocess
import sys
from . import branch
from . import tag
from . import commit
from . import config
from .files import ModifiedFile
@ -42,10 +44,16 @@ from .exceptions import CannotFindRepository
from .exceptions import GitException
from .exceptions import GitCommandFailedException
from .exceptions import MergeConflict
from .exceptions import NonexistentRefException
BRANCH_ALIAS_MARKER = ' -> '
class Repository(ref_container.RefContainer):
_git_command = None
def setCommand(self, command):
self._git_command = command
############################# internal methods #############################
_loggingEnabled = False
def _getWorkingDirectory(self):
@ -60,7 +68,8 @@ class Repository(ref_container.RefContainer):
def _executeGitCommand(self, command, cwd = None):
if cwd is None:
cwd = self._getWorkingDirectory()
command = str(command)
command = '%s %s' % (self._git_command, str(command))
self._logGitCommand(command, cwd)
returned = subprocess.Popen(command,
shell = True,
@ -90,22 +99,34 @@ class Repository(ref_container.RefContainer):
############################## remote repositories #############################
class RemoteRepository(Repository):
def __init__(self, url):
def __init__(self, url, command = 'git'):
self.setCommand(command)
super(RemoteRepository, self).__init__()
self.url = url
def _getRefs(self, prefix):
output = self._executeGitCommandAssertSuccess("git ls-remote %s" % (self.url,))
def _getRefs(self, prefix = ''):
output = self._executeGitCommandAssertSuccess("ls-remote %s" % (self.url,))
for output_line in output.stdout:
commit, refname = output_line.split()
if refname.startswith(prefix):
yield refname[len(prefix):]
yield refname[len(prefix):], commit.strip()
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):
return self._getRefsAsClass('refs/heads/', branch.RemoteBranch)
def getTags(self):
return self._getRefsAsClass('refs/tags/', tag.RemoteTag)
############################## local repositories ##############################
class LocalRepository(Repository):
def __init__(self, path):
def __init__(self, path, command = 'git'):
self.setCommand(command)
super(LocalRepository, self).__init__()
self.path = path
self.config = config.GitConfiguration(self)
@ -117,12 +138,12 @@ class LocalRepository(Repository):
def _getCommitByHash(self, sha):
return commit.Commit(self, sha)
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):
return self._getCommitByRefName(sha)
def getGitVersion(self):
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)
if version_match is None:
raise GitException("Cannot extract git version (unfamiliar output format %r?)" % version_output)
@ -135,7 +156,7 @@ class LocalRepository(Repository):
if not os.path.isdir(self.path):
raise GitException("Cannot create repository in %s - "
"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):
if isinstance(repo, LocalRepository):
repo = repo.path
@ -145,11 +166,11 @@ class LocalRepository(Repository):
raise TypeError("Cannot clone from %r" % (repo,))
return 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 ###########################
def getBranches(self):
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("*"):
git_branch_line = git_branch_line[1:]
git_branch_line = git_branch_line.strip()
@ -159,8 +180,13 @@ class LocalRepository(Repository):
else:
returned.append(branch.LocalBranch(self, git_branch_line))
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):
command = "git log --pretty=format:%%H %s" % specs
command = "log --pretty=format:%%H %s" % specs
if not includeMerges:
command += " --no-merges"
for c in self._executeGitCommandAssertSuccess(command).stdout:
@ -172,7 +198,7 @@ class LocalRepository(Repository):
return list(self._getCommits(spec, includeMerges = includeMerges))
def getCurrentBranch(self):
#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()
if not branch_name.startswith("*"):
continue
@ -183,7 +209,7 @@ class LocalRepository(Repository):
def getRemotes(self):
config_dict = self.config.getDict()
returned = []
for line in self._getOutputAssertSuccess("git remote show -n").splitlines():
for line in self._getOutputAssertSuccess("remote show -n").splitlines():
line = line.strip()
returned.append(remotes.Remote(self, line, config_dict.get('remote.%s.url' % line.strip())))
return returned
@ -194,7 +220,7 @@ class LocalRepository(Repository):
a = a.getHead()
if isinstance(b, ref.Ref):
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:
return commit.Commit(self, returned.stdout.read().strip())
# make sure this is not a misc. error with git
@ -203,7 +229,7 @@ class LocalRepository(Repository):
################################ Querying Status ###############################
def containsCommit(self, commit):
try:
self._executeGitCommandAssertSuccess("git log -1 %s" % (commit,))
self._executeGitCommandAssertSuccess("log -1 %s" % (commit,))
except GitException:
return False
return True
@ -212,11 +238,24 @@ class LocalRepository(Repository):
def _getFiles(self, *flags):
flags = ["--exclude-standard"] + list(flags)
return [f.strip()
for f in self._getOutputAssertSuccess("git ls-files %s" % (" ".join(flags))).splitlines()]
def _getRawDiff(self, *flags):
for f in self._getOutputAssertSuccess("ls-files %s" % (" ".join(flags))).splitlines()]
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)
return [ModifiedFile(line.split()[-1]) for line in
self._getOutputAssertSuccess("git diff --raw %s" % flags).splitlines()]
modified_files = []
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):
if self.isInitialized():
return self._getRawDiff('--cached')
@ -225,6 +264,8 @@ class LocalRepository(Repository):
return self._getFiles()
def getChangedFiles(self):
return self._getRawDiff()
def getDeletedFiles(self):
return self._getRawDiff(fileStatuses = ['D'])
def getUntrackedFiles(self):
return self._getFiles("--others")
def isInitialized(self):
@ -244,7 +285,14 @@ class LocalRepository(Repository):
raise NotImplementedError()
################################ Staging content ###############################
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):
return self.add('.')
################################## Committing ##################################
@ -261,23 +309,30 @@ class LocalRepository(Repository):
if match:
return commit.Commit(self, match.group(1))
return None
def commit(self, message, allowEmpty=False):
command = "git commit -m %s" % quote_for_shell(message)
def commit(self, message, allowEmpty = False, commitAll = False):
args = ''
if commitAll:
args = args + '--all'
command = "commit %s -m %s" % (args, quote_for_shell(message))
if allowEmpty:
command += " --allow-empty"
output = self._getOutputAssertSuccess(command)
return self._deduceNewCommitFromCommitOutput(output)
################################ Changing state ################################
def createBranch(self, name, startingPoint=None):
command = "git branch %s " % name
def _createBranchOrTag(self, objname, name, startingPoint, returned_class):
command = "%s %s " % (objname, name)
if startingPoint is not None:
command += self._normalizeRefName(startingPoint)
self._executeGitCommandAssertSuccess(command)
return branch.LocalBranch(self, name)
return returned_class(self, name)
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:
thing = ""
command = "git checkout %s" % (self._normalizeRefName(thing),)
command = "checkout %s" % (self._normalizeRefName(thing),)
if targetBranch is not None:
command += " -b %s" % (targetBranch,)
if files:
@ -285,7 +340,7 @@ class LocalRepository(Repository):
self._executeGitCommandAssertSuccess(command)
def mergeMultiple(self, srcs, allowFastForward = True, log = False, message = None):
try:
self._executeGitCommandAssertSuccess(CMD("git merge",
self._executeGitCommandAssertSuccess(CMD("merge",
" ".join(self._normalizeRefName(src) for src in srcs),
"--no-ff" if not allowFastForward else None,
"--log" if log else None,
@ -299,7 +354,7 @@ class LocalRepository(Repository):
def merge(self, src, *args, **kwargs):
return self.mergeMultiple([src], *args, **kwargs)
def _reset(self, flag, thing):
command = "git reset %s %s" % (
command = "reset %s %s" % (
flag,
self._normalizeRefName(thing))
self._executeGitCommandAssertSuccess(command)
@ -310,7 +365,7 @@ class LocalRepository(Repository):
def resetMixed(self, thing = "HEAD"):
return self._reset("--mixed", thing)
def _clean(self, flags):
self._executeGitCommandAssertSuccess("git clean -q " + flags)
self._executeGitCommandAssertSuccess("clean -q " + flags)
def cleanIgnoredFiles(self):
"""Cleans files that match the patterns in .gitignore"""
return self._clean("-f -X")
@ -318,16 +373,16 @@ class LocalRepository(Repository):
return self._clean("-f -d")
################################# collaboration ################################
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)
def fetch(self, repo = None):
command = "git fetch"
command = "fetch"
if repo is not None:
command += " "
command += self._asURL(repo)
self._executeGitCommandAssertSuccess(command)
def pull(self, repo = None):
command = "git pull"
command = "pull"
if repo is not None:
command += " "
command += self._asURL(repo)
@ -346,7 +401,7 @@ class LocalRepository(Repository):
returned = "+%s" % returned
return returned
def push(self, remote = None, fromBranch = None, toBranch = None, force = False):
command = "git push"
command = "push"
#build push arguments
refspec = self._getRefspec(toBranch = toBranch, fromBranch = fromBranch, force = force)
@ -360,24 +415,22 @@ class LocalRepository(Repository):
remote = remote.path
if remote is not None and not isinstance(remote, basestring):
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)
def rebase(self, src):
self._executeGitCommandAssertSuccess("git rebase %s" % self._normalizeRefName(src))
self._executeGitCommandAssertSuccess("rebase %s" % self._normalizeRefName(src))
#################################### Stashes ###################################
def saveStash(self, name = None):
command = "git stash save"
command = "stash save"
if name is not None:
command += " %s" % name
self._executeGitCommandAssertSuccess(command)
def popStash(self, arg = None):
command = "git stash pop"
command = "stash pop"
if arg is not None:
command += " %s" % arg
self._executeGitCommandAssertSuccess(command)
################################# Configuration ################################
def getConfig(self):
return dict(s.split("=",1) for s in self._getOutputAssertSuccess("git config -l"))
################################### Shortcuts ##################################
def clone(source, location):

33
libs/git/tag.py

@ -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

0
libs/git/utils.py

Loading…
Cancel
Save