Merge branch 'source_control-executable' of https://github.com/skyl/ansible into skyl-source_control-executable

reviewable/pr18780/r1
James Cammarata 11 years ago
commit ccafe66778

@ -50,6 +50,13 @@ options:
description:
- If C(yes), any modified files in the working
tree will be discarded.
executable:
required: false
default: null
version_added: "1.4"
description:
- Path to bzr executable to use. If not supplied,
the normal mechanism for resolving binary paths will be used.
'''
EXAMPLES = '''
@ -58,67 +65,79 @@ EXAMPLES = '''
'''
import re
import tempfile
def get_version(dest):
''' samples the version of the bzr branch'''
os.chdir(dest)
cmd = "bzr revno"
revno = os.popen(cmd).read().strip()
return revno
def clone(module, parent, dest, version):
''' makes a new bzr branch if it does not already exist '''
dest_dirname = os.path.dirname(dest)
try:
os.makedirs(dest_dirname)
except:
pass
os.chdir(dest_dirname)
if version.lower() != 'head':
cmd = "bzr branch -r %s %s %s" % (version, parent, dest)
else:
cmd = "bzr branch %s %s" % (parent, dest)
return module.run_command(cmd, check_rc=True)
def has_local_mods(dest):
os.chdir(dest)
cmd = "bzr status -S"
lines = os.popen(cmd).read().splitlines()
lines = filter(lambda c: not re.search('^\\?\\?.*$', c), lines)
return len(lines) > 0
def reset(module,dest,force):
'''
Resets the index and working tree to head.
Discards any changes to tracked files in the working
tree since that commit.
'''
os.chdir(dest)
if not force and has_local_mods(dest):
module.fail_json(msg="Local modifications exist in branch (force=no).")
return module.run_command("bzr revert", check_rc=True)
def fetch(module, dest, version):
''' updates branch from remote sources '''
os.chdir(dest)
if version.lower() != 'head':
(rc, out, err) = module.run_command("bzr pull -r %s" % version)
else:
(rc, out, err) = module.run_command("bzr pull")
if rc != 0:
module.fail_json(msg="Failed to pull")
return (rc, out, err)
def switch_version(module, dest, version):
''' once pulled, switch to a particular revno or revid'''
os.chdir(dest)
cmd = ''
if version.lower() != 'head':
cmd = "bzr revert -r %s" % version
else:
cmd = "bzr revert"
return module.run_command(cmd, check_rc=True)
class Bzr(object):
def __init__(self, module, parent, dest, version, bzr_path):
self.module = module
self.parent = parent
self.dest = dest
self.version = version
self.bzr_path = bzr_path
def _command(self, args_list, **kwargs):
(rc, out, err) = self.module.run_command(
[self.bzr_path] + args_list, **kwargs)
return (rc, out, err)
def get_version(self):
'''samples the version of the bzr branch'''
os.chdir(self.dest)
cmd = "%s revno" % self.bzr_path
revno = os.popen(cmd).read().strip()
return revno
def clone(self):
'''makes a new bzr branch if it does not already exist'''
dest_dirname = os.path.dirname(self.dest)
try:
os.makedirs(dest_dirname)
except:
pass
os.chdir(dest_dirname)
if self.version.lower() != 'head':
args_list = ["branch", "-r", self.version, self.parent, self.dest]
else:
args_list = ["branch", self.parent, self.dest]
return self._command(args_list, check_rc=True)
def has_local_mods(self):
os.chdir(self.dest)
cmd = "%s status -S" % self.bzr_path
lines = os.popen(cmd).read().splitlines()
lines = filter(lambda c: not re.search('^\\?\\?.*$', c), lines)
return len(lines) > 0
def reset(self, force):
'''
Resets the index and working tree to head.
Discards any changes to tracked files in the working
tree since that commit.
'''
os.chdir(self.dest)
if not force and self.has_local_mods():
self.module.fail_json(msg="Local modifications exist in branch (force=no).")
return self._command(["revert"], check_rc=True)
def fetch(self):
'''updates branch from remote sources'''
os.chdir(self.dest)
if self.version.lower() != 'head':
(rc, out, err) = self._command(["pull", "-r", self.version])
else:
(rc, out, err) = self._command(["pull"])
if rc != 0:
self.module.fail_json(msg="Failed to pull")
return (rc, out, err)
def switch_version(self):
'''once pulled, switch to a particular revno or revid'''
os.chdir(self.dest)
if self.version.lower() != 'head':
args_list = ["revert", "-r", self.version]
else:
args_list = ["revert"]
return self._command(args_list, check_rc=True)
# ===========================================
@ -128,7 +147,8 @@ def main():
dest=dict(required=True),
name=dict(required=True, aliases=['parent']),
version=dict(default='head'),
force=dict(default='yes', type='bool')
force=dict(default='yes', type='bool'),
executable=dict(default=None),
)
)
@ -136,34 +156,38 @@ def main():
parent = module.params['name']
version = module.params['version']
force = module.params['force']
bzr_path = module.params['executable'] or module.get_bin_path('bzr', True)
bzrconfig = os.path.join(dest, '.bzr', 'branch', 'branch.conf')
rc, out, err, status = (0, None, None, None)
bzr = Bzr(module, parent, dest, version, bzr_path)
# if there is no bzr configuration, do a branch operation
# else pull and switch the version
before = None
local_mods = False
if not os.path.exists(bzrconfig):
(rc, out, err) = clone(module, parent, dest, version)
(rc, out, err) = bzr.clone()
else:
# else do a pull
local_mods = has_local_mods(dest)
before = get_version(dest)
(rc, out, err) = reset(module, dest, force)
local_mods = bzr.has_local_mods()
before = bzr.get_version()
(rc, out, err) = bzr.reset(force)
if rc != 0:
module.fail_json(msg=err)
(rc, out, err) = fetch(module, dest, version)
(rc, out, err) = bzr.fetch()
if rc != 0:
module.fail_json(msg=err)
# switch to version specified regardless of whether
# we cloned or pulled
(rc, out, err) = switch_version(module, dest, version)
(rc, out, err) = bzr.switch_version()
# determine if we changed anything
after = get_version(dest)
after = bzr.get_version()
changed = False
if before != after or local_mods:

@ -73,6 +73,13 @@ options:
- If C(yes), repository will be updated using the supplied
remote. Otherwise the repo will be left untouched.
Prior to 1.2, this was always 'yes' and could not be disabled.
executable:
required: false
default: null
version_added: "1.4"
description:
- Path to git executable to use. If not supplied,
the normal mechanism for resolving binary paths will be used.
notes:
- If the task seems to be hanging, first verify remote host is in C(known_hosts).
SSH will prompt user to authorize the first contact with a remote host. One solution is to add
@ -304,6 +311,7 @@ def main():
force=dict(default='yes', type='bool'),
depth=dict(default=None, type='int'),
update=dict(default='yes', type='bool'),
executable=dict(default=None),
),
supports_check_mode=True
)
@ -315,8 +323,8 @@ def main():
force = module.params['force']
depth = module.params['depth']
update = module.params['update']
git_path = module.params['executable'] or module.get_bin_path('git', True)
git_path = module.get_bin_path('git', True)
gitconfig = os.path.join(dest, '.git', 'config')
rc, out, err, status = (0, None, None, None)

@ -22,10 +22,7 @@
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
import os
import shutil
import ConfigParser
from subprocess import Popen, PIPE
DOCUMENTATION = '''
---
@ -68,6 +65,13 @@ options:
required: false
default: "no"
choices: [ "yes", "no" ]
executable:
required: false
default: null
version_added: "1.4"
description:
- Path to hg executable to use. If not supplied,
the normal mechanism for resolving binary paths will be used.
notes:
- If the task seems to be hanging, first verify remote host is in C(known_hosts).
SSH will prompt user to authorize the first contact with a remote host. One solution is to add
@ -98,6 +102,7 @@ def _set_hgrc(hgrc, vals):
parser.write(f)
f.close()
def _undo_hgrc(hgrc, vals):
parser = ConfigParser.SafeConfigParser()
parser.read(hgrc)
@ -111,94 +116,105 @@ def _undo_hgrc(hgrc, vals):
parser.write(f)
f.close()
def _hg_command(module, args_list):
(rc, out, err) = module.run_command(['hg'] + args_list)
return (rc, out, err)
def _hg_list_untracked(module, dest):
return _hg_command(module, ['purge', '-R', dest, '--print'])
def get_revision(module, dest):
"""
hg id -b -i -t returns a string in the format:
"<changeset>[+] <branch_name> <tag>"
This format lists the state of the current working copy,
and indicates whether there are uncommitted changes by the
plus sign. Otherwise, the sign is omitted.
Read the full description via hg id --help
"""
(rc, out, err) = _hg_command(module, ['id', '-b', '-i', '-t', '-R', dest])
if rc != 0:
module.fail_json(msg=err)
else:
return out.strip('\n')
def has_local_mods(module, dest):
now = get_revision(module, dest)
if '+' in now:
return True
else:
return False
class Hg(object):
def __init__(self, module, dest, repo, revision, hg_path):
self.module = module
self.dest = dest
self.repo = repo
self.revision = revision
self.hg_path = self.hg_path
def _command(self, args_list):
(rc, out, err) = self.module.run_command([self.hg_path] + args_list)
return (rc, out, err)
def _list_untracked(self):
return self._command(['purge', '-R', self.dest, '--print'])
def get_revision(self):
"""
hg id -b -i -t returns a string in the format:
"<changeset>[+] <branch_name> <tag>"
This format lists the state of the current working copy,
and indicates whether there are uncommitted changes by the
plus sign. Otherwise, the sign is omitted.
Read the full description via hg id --help
"""
(rc, out, err) = self._command(['id', '-b', '-i', '-t', '-R', self.dest])
if rc != 0:
self.module.fail_json(msg=err)
else:
return out.strip('\n')
def hg_discard(module, dest):
before = has_local_mods(module, dest)
if not before:
return False
def has_local_mods(self):
now = self.get_revision()
if '+' in now:
return True
else:
return False
def discard(self):
before = self.has_local_mods()
if not before:
return False
(rc, out, err) = _hg_command(module, ['update', '-C', '-R', dest])
if rc != 0:
module.fail_json(msg=err)
(rc, out, err) = self._command(['update', '-C', '-R', self.dest])
if rc != 0:
self.module.fail_json(msg=err)
after = has_local_mods(module, dest)
if before != after and not after: # no more local modification
return True
after = self.has_local_mods()
if before != after and not after: # no more local modification
return True
def hg_purge(module, dest):
hgrc = os.path.join(dest, '.hg/hgrc')
purge_option = [('extensions', 'purge', '')]
_set_hgrc(hgrc, purge_option) # enable purge extension
# before purge, find out if there are any untracked files
(rc1, out1, err1) = _hg_list_untracked(module, dest)
if rc1 != 0:
module.fail_json(msg=err)
# there are some untrackd files
if out1 != '':
(rc2, out2, err2) = _hg_command(module, ['purge', '-R', dest])
if rc2 == 0:
_undo_hgrc(hgrc, purge_option)
def purge(self):
hgrc = os.path.join(self.dest, '.hg/hgrc')
purge_option = [('extensions', 'purge', '')]
_set_hgrc(hgrc, purge_option) # enable purge extension
# before purge, find out if there are any untracked files
(rc1, out1, err1) = self._list_untracked()
if rc1 != 0:
self.module.fail_json(msg=err1)
# there are some untrackd files
if out1 != '':
(rc2, out2, err2) = self._command(['purge', '-R', self.dest])
if rc2 == 0:
_undo_hgrc(hgrc, purge_option)
else:
self.module.fail_json(msg=err2)
return True
else:
module.fail_json(msg=err)
return True
else:
return False
def hg_cleanup(module, dest, force, purge):
discarded = False
purged = False
if force:
discarded = hg_discard(module, dest)
if purge:
purged = hg_purge(module, dest)
if discarded or purged:
return True
else:
return False
return False
def cleanup(self, force, purge):
discarded = False
purged = False
def hg_pull(module, dest, revision, repo):
return _hg_command(module, ['pull', '-r', revision, '-R', dest, repo])
if force:
discarded = self.discard()
if purge:
purged = self.purge()
if discarded or purged:
return True
else:
return False
def pull(self):
return self._command(
['pull', '-r', self.revision, '-R', self.dest, self.repo])
def hg_update(module, dest, revision):
return _hg_command(module, ['update', '-R', dest])
def update(self):
return self._command(['update', '-R', self.dest])
def hg_clone(module, repo, dest, revision):
return _hg_command(module, ['clone', repo, dest, '-r', revision])
def clone(self):
return self._command(['clone', self.repo, self.dest, '-r', self.revision])
def switch_version(module, dest, revision):
return _hg_command(module, ['update', '-r', revision, '-R', dest])
def switch_version(self):
return self._command(['update', '-r', self.revision, '-R', self.dest])
# ===========================================
@ -209,7 +225,8 @@ def main():
dest = dict(required=True),
revision = dict(default="default", aliases=['version']),
force = dict(default='yes', type='bool'),
purge = dict(default='no', type='bool')
purge = dict(default='no', type='bool'),
executable = dict(default=None),
),
)
repo = module.params['repo']
@ -217,6 +234,7 @@ def main():
revision = module.params['revision']
force = module.params['force']
purge = module.params['purge']
hg_path = module.parames['executable'] or module.get_bin_path('hg', True)
hgrc = os.path.join(dest, '.hg/hgrc')
# initial states
@ -224,29 +242,31 @@ def main():
changed = False
cleaned = False
hg = Hg(module, dest, repo, revision, hg_path)
# If there is no hgrc file, then assume repo is absent
# and perform clone. Otherwise, perform pull and update.
if not os.path.exists(hgrc):
(rc, out, err) = hg_clone(module, repo, dest, revision)
(rc, out, err) = hg.clone()
if rc != 0:
module.fail_json(msg=err)
else:
# get the current state before doing pulling
before = get_revision(module, dest)
before = hg.get_revision()
# can perform force and purge
cleaned = hg_cleanup(module, dest, force, purge)
cleaned = hg.cleanup(force, purge)
(rc, out, err) = hg_pull(module, dest, revision, repo)
(rc, out, err) = hg.pull()
if rc != 0:
module.fail_json(msg=err)
(rc, out, err) = hg_update(module, dest, revision)
(rc, out, err) = hg.update()
if rc != 0:
module.fail_json(msg=err)
switch_version(module, dest, revision)
after = get_revision(module, dest)
hg.switch_version()
after = hg.get_revision()
if before != after or cleaned:
changed = True
module.exit_json(before=before, after=after, changed=changed, cleaned=cleaned)

@ -63,6 +63,13 @@ options:
- --password parameter passed to svn.
required: false
default: null
executable:
required: false
default: null
version_added: "1.4"
description:
- Path to svn executable to use. If not supplied,
the normal mechanism for resolving binary paths will be used.
'''
EXAMPLES = '''
@ -71,19 +78,27 @@ EXAMPLES = '''
'''
import re
import tempfile
class Subversion(object):
def __init__(self, module, dest, repo, revision, username, password):
def __init__(
self, module, dest, repo, revision, username, password, svn_path):
self.module = module
self.dest = dest
self.repo = repo
self.revision = revision
self.username = username
self.password = password
self.svn_path = svn_path
def _exec(self, args):
bits = ["svn --non-interactive --trust-server-cert --no-auth-cache", ]
bits = [
self.svn_path,
'--non-interactive',
'--trust-server-cert',
'--no-auth-cache',
]
if self.username:
bits.append("--username '%s'" % self.username)
if self.password:
@ -147,6 +162,7 @@ def main():
force=dict(default='yes', type='bool'),
username=dict(required=False),
password=dict(required=False),
executable=dict(default=None),
),
supports_check_mode=True
)
@ -157,8 +173,9 @@ def main():
force = module.params['force']
username = module.params['username']
password = module.params['password']
svn_path = module.params['executable'] or module.get_bin_path('svn', True)
svn = Subversion(module, dest, repo, revision, username, password)
svn = Subversion(module, dest, repo, revision, username, password, svn_path)
if not os.path.exists(dest):
before = None

Loading…
Cancel
Save