diff --git a/salt/modules/git.py b/salt/modules/git.py index 4753d3c5ff..e630a09ca3 100644 --- a/salt/modules/git.py +++ b/salt/modules/git.py @@ -431,6 +431,7 @@ def submodule(cwd, init=True, opts=None, user=None): cmd = 'git submodule update {0} {1}'.format('--init' if init else '', opts) return _git_run(cmd, cwd=cwd, runas=user) + def status(cwd, user=None): ''' Return the status of the repository. The returned format uses the status @@ -452,6 +453,7 @@ def status(cwd, user=None): status.append((state, filename)) return status + def add(cwd, file_name, user=None, opts=None): ''' add a file to git @@ -474,6 +476,7 @@ def add(cwd, file_name, user=None, opts=None): cmd = 'git add {0} {1}'.format(file_name, opts) return _git_run(cmd, cwd=cwd, runas=user) + def rm(cwd, file_name, user=None, opts=None): ''' Remove a file from git @@ -547,3 +550,82 @@ def push(cwd, remote_name, branch='master', user=None, opts=None, identity=None) opts = '' cmd = 'git push {0} {1} {2}'.format(remote_name, branch, opts) return _git_run(cmd, cwd=cwd, runas=user, identity=identity) + + +def remotes(cwd, user=None): + ''' + Get remotes like git remote -v + + cwd + The path to the Git repository + + user : None + Run git as a user other than what the minion runs as + + CLI Example:: + + salt '*' git.remotes /path/to/repo + ''' + cmd = 'git remote' + ret = _git_run(cmd, cwd=cwd, runas=user) + res = dict() + for remote_name in ret.splitlines(): + remote = remote_name.strip() + res[remote] = remote_get(cwd, remote, user=user) + return res + + +def remote_get(cwd, remote='origin', user=None): + ''' + get fetch und push url for a specified remote name + + remote : origin + the remote name used to define the fetch and push url + + user : None + Run git as a user other than what the minion runs as + + CLI Example:: + + salt '*' git.remote_get /path/to/repo + salt '*' git.remote_get /path/to/repo upstream + ''' + try: + cmd = 'git remote show -n {0}'.format(remote) + ret = _git_run(cmd, cwd=cwd, runas=user) + lines = ret.splitlines() + remote_fetch_url = lines[1].replace('Fetch URL: ', '').strip() + remote_push_url = lines[2].replace('Push URL: ', '').strip() + if remote_fetch_url != remote and remote_push_url != remote: + res = (remote_fetch_url, remote_push_url) + return res + else: + return None + except exceptions.CommandExecutionError: + return None + + +def remote_set(cwd, name='origin', url=None, user=None): + ''' + sets a remote with name and url like git remote add + + remote_name : origin + defines the remote name + + remote_url : None + defines the remote url shut not be null! + + user : None + Run git as a user other than what the minion runs as + + CLI Example:: + + salt '*' git.remote_set /path/to/repo remote_url=git@github.com:saltstack/salt.git + salt '*' git.remote_set /path/to/repo origin git@github.com:saltstack/salt.git + ''' + if remote_get(cwd, name): + cmd = 'git remote rm {0}'.format(name) + _git_run(cmd, cwd=cwd, runas=user) + cmd = 'git remote add {0} {1}'.format(name, url) + _git_run(cmd, cwd=cwd, runas=user) + return remote_get(cwd=cwd, remote=name, user=None) diff --git a/salt/states/git.py b/salt/states/git.py index be1aa54902..45c6c1ecce 100644 --- a/salt/states/git.py +++ b/salt/states/git.py @@ -39,6 +39,7 @@ def latest(name, submodules=False, mirror=False, bare=False, + remote_name='origin', identity=None, **kwargs): ''' @@ -63,6 +64,10 @@ def latest(name, bare True if the repository is to be a bare clone of the remote repository. This is incompatible with rev, as nothing will be checked out. + remote_name + defines a different remote name. + For the first clone the given name is set to the default remote, + else it is just a additional remote. (Default: 'origin') identity A path to a private key to use over SSH ''' @@ -93,19 +98,39 @@ def latest(name, ('Repository {0} update is probably required (current ' 'revision is {1})').format(target, current_rev)) + # if remote_name is defined set fetch_opts to remote_name + if not remote_name == 'origin': + fetch_opts = remote_name + else: + fetch_opts = '' + + # check remote if fetch_url not == name set it + remote = __salt__['git.remote_get'](target, + remote=remote_name, + user=runas) + if remote == None or not remote[0] == name: + __salt__['git.remote_set'](target, + remote_name=remote_name, + remote_url=name, + user=runas) + ret['changes']['remote/{0}'.format(remote_name)] = "{0} => {1}".format(str(remote), name) + # check if rev is already present in repo, git-fetch otherwise if bare: __salt__['git.fetch'](target, + opts=fetch_opts, user=runas, identity=identity) elif rev: - cmd = "git rev-parse "+rev + cmd = "git rev-parse " + rev retcode = __salt__['cmd.retcode'](cmd, cwd=target, runas=runas) + # there is a issues #3938 addressing this if 0 != retcode: __salt__['git.fetch'](target, + opts=fetch_opts, user=runas, identity=identity) @@ -115,8 +140,10 @@ def latest(name, cmd = "git symbolic-ref -q HEAD > /dev/null" retcode = __salt__['cmd.retcode'](cmd, cwd=target, runas=runas) if 0 == retcode: - __salt__['git.fetch' if bare else 'git.pull']( - target, user=runas, identity=identity) + __salt__['git.fetch' if bare else 'git.pull'](target, + opts=fetch_opts, + user=runas, + identity=identity) if submodules: __salt__['git.submodule'](target, user=runas, @@ -161,6 +188,10 @@ def latest(name, try: # make the clone opts = '--mirror' if mirror else '--bare' if bare else '' + # if remote_name is not origin add --origin to opts + if not remote_name == 'origin': + opts += ' --origin {0}'.format(remote_name) + # do the clone __salt__['git.clone'](target, name, user=runas,