Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
ansible
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
ansible
Commits
42daffdb
Commit
42daffdb
authored
Feb 02, 2013
by
Michael DeHaan
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1948 from yeukhon/devel
hg module cleaned up
parents
f7aaa5cc
cc6fc149
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
127 additions
and
136 deletions
+127
-136
library/hg
+127
-136
No files found.
library/hg
View file @
42daffdb
...
...
@@ -4,7 +4,8 @@
# (c) 2013, Yeukhon Wong <yeukhon@acm.org>
#
# This module was originally inspired by Brad Olson's ansible-module-mercurial
# <https://github.com/bradobro/ansible-module-mercurial>.
# <https://github.com/bradobro/ansible-module-mercurial>. This module tends
# to follow the git module implementation.
#
# This file is part of Ansible
#
...
...
@@ -37,7 +38,7 @@ author: Yeukhon Wong
options:
repo:
description:
- The repository
location
.
- The repository
address
.
required: true
default: null
dest:
...
...
@@ -45,62 +46,46 @@ options:
- Absolute path of where the repository should be cloned to.
required: true
default: null
state:
description:
- C(hg clone) is performed when state is set to C(present). C(hg pull) and C(hg update) is
performed when state is set to C(latest). If you want the latest copy of the repository,
just rely on C(present). C(latest) assumes the repository is already on disk.
required: false
default: present
choices: [ "present", "absent", "latest" ]
revision:
description:
- Equivalent C(-r) option in hg command
, which can either be a changeset number or a branch
name.
- Equivalent C(-r) option in hg command
which could be the changeset, revision number,
branch name or even tag.
required: false
default: "default"
force:
description:
- Whether to discard uncommitted changes and remove untracked files or not. Basically, it
combines C(hg up -C) and C(hg purge).
- Discards uncommited changes. Runs C(hg update -C).
required: false
default: "yes"
choices: [
"yes", "no"
]
examples
:
- code: "hg: repo=https://bitbucket.org/user/repo_name dest=/home/user/repo_name"
description: Clone the default branch of repo_name.
- code: "hg: repo=https://bitbucket.org/user/repo_name dest=/home/user/repo_name force=yes state=latest"
description: Ensure the repository at dest is latest and discard any uncommitted and/or untracked files.
choices: [
yes, no
]
purge:
description
:
- Delets untracked files. Runs C(hg purge). Note this requires C(purge) extension to
be enabled if C(purge=yes). This module will modify hgrc file on behalf of the user
and undo the changes before exiting the task.
required: false
default: "no"
choices: [ yes, no ]
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
C(StrictHostKeyChecking no) in C(.ssh/config) which will accept and authorize the connection
on behalf of the user. However, if you run as a different user such as setting sudo to True),
for example, root will not look at the user .ssh/config setting.
examples:
- code: "hg: repo=https://bitbucket.org/user/repo1 dest=/home/user/repo1 revision=stable purge=yes"
description: Ensure the current working copy is inside the stable branch and deletes untracked files if any.
requirements: [ ]
'''
class
HgError
(
Exception
):
""" Custom exception class to report hg command error. """
def
__init__
(
self
,
msg
,
stderr
=
''
):
self
.
msg
=
msg
+
\
"
\n\n
Extra information on this error:
\n
"
+
\
stderr
def
__str__
(
self
):
return
self
.
msg
def
_set_hgrc
(
hgrc
,
vals
):
# val is a list of triple-tuple of the form [(section, option, value),...]
parser
=
ConfigParser
.
SafeConfigParser
()
parser
.
read
(
hgrc
)
# val is a list of triple-tuple of the form [(section, option, value),...]
for
each
in
vals
:
section
,
option
,
value
=
each
(
section
,
option
,
value
)
=
each
if
not
parser
.
has_section
(
section
):
parser
.
add_section
(
section
)
parser
.
set
(
section
,
option
,
value
)
...
...
@@ -114,7 +99,7 @@ def _undo_hgrc(hgrc, vals):
parser
.
read
(
hgrc
)
for
each
in
vals
:
section
,
option
,
value
=
each
(
section
,
option
,
value
)
=
each
if
parser
.
has_section
(
section
):
parser
.
remove_option
(
section
,
option
)
...
...
@@ -124,137 +109,143 @@ def _undo_hgrc(hgrc, vals):
def
_hg_command
(
module
,
args_list
):
(
rc
,
out
,
err
)
=
module
.
run_command
([
'hg'
]
+
args_list
)
return
(
out
,
err
,
rc
)
return
(
rc
,
out
,
err
)
def
_hg_discard
(
module
,
dest
):
out
,
err
,
code
=
_hg_command
(
module
,
[
'up'
,
'-C'
,
'-R'
,
dest
])
if
code
!=
0
:
raise
HgError
(
err
)
def
_hg_list_untracked
(
module
,
dest
):
return
_hg_command
(
module
,
[
'purge'
,
'-R'
,
dest
,
'--print'
])
def
_hg_purge
(
module
,
dest
):
hgrc
=
os
.
path
.
join
(
dest
,
'.hg/hgrc'
)
purge_option
=
[(
'extensions'
,
'purge'
,
''
)]
_set_hgrc
(
hgrc
,
purge_option
)
out
,
err
,
code
=
_hg_command
(
module
,
[
'purge'
,
'-R'
,
dest
])
if
code
==
0
:
_undo_hgrc
(
hgrc
,
purge_option
)
else
:
raise
HgError
(
err
)
def
_hg_verify
(
module
,
dest
):
error1
=
"hg verify failed."
error2
=
"{dest} is not a repository."
.
format
(
dest
=
dest
)
out
,
err
,
code
=
_hg_command
(
module
,
[
'verify'
,
'-R'
,
dest
])
if
code
==
1
:
raise
HgError
(
error1
,
stderr
=
err
)
elif
code
==
255
:
raise
HgError
(
error2
,
stderr
=
err
)
elif
code
==
0
:
return
True
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.
def
_post_op_hg_revision_check
(
module
,
dest
,
revision
):
Read the full description via hg id --help
"""
Verify the tip is the same as `revision`.
(
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
'
)
This function is usually called after some hg operations
such as `clone`. However, this check is skipped if `revision`
is the string `default` since it will result an error.
Instead, pull is performed.
def
has_local_mods
(
module
,
dest
):
now
=
get_revision
(
module
,
dest
)
if
'+'
in
now
:
return
True
else
:
return
False
"""
def
hg_discard
(
module
,
dest
):
before
=
has_local_mods
(
module
,
dest
)
if
not
before
:
return
False
err1
=
"Unable to perform hg tip."
err2
=
"tip is different from
%
s. See below for extended summary."
%
revision
(
rc
,
out
,
err
)
=
_hg_command
(
module
,
[
'update'
,
'-C'
,
'-R'
,
dest
])
if
rc
!=
0
:
module
.
fail_json
(
msg
=
err
)
if
revision
==
'default'
:
out
,
err
,
code
=
_hg_command
(
module
,
[
'pull'
,
'-R'
,
dest
])
if
"no changes found"
in
out
:
after
=
has_local_mods
(
module
,
dest
)
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
)
else
:
raise
HgError
(
err2
,
stderr
=
out
)
else
:
out
,
err
,
code
=
_hg_command
(
module
,
[
'tip'
,
'-R'
,
dest
])
if
revision
in
out
:
# revision should be part of the output (changeset: $revision ...)
module
.
fail_json
(
msg
=
err
)
return
True
else
:
if
code
!=
0
:
# something went wrong with hg tip
raise
HgError
(
err1
,
stderr
=
err
)
else
:
# hg tip is fine, but tip != revision
raise
HgError
(
err2
,
stderr
=
out
)
def
force_and_clean
(
module
,
dest
):
_hg_discard
(
module
,
dest
)
_hg_purge
(
module
,
dest
)
def
pull_and_update
(
module
,
repo
,
dest
,
revision
,
force
):
if
force
==
'yes'
:
force_and_clean
(
module
,
dest
)
if
_hg_verify
(
module
,
dest
):
cmd1
=
[
'pull'
,
'-R'
,
dest
,
'-r'
,
revision
]
out
,
err
,
code
=
_hg_command
(
module
,
cmd1
)
if
code
==
1
:
raise
HgError
(
"Unable to perform pull on
%
s"
%
dest
,
stderr
=
err
)
elif
code
==
0
:
cmd2
=
[
'update'
,
'-R'
,
dest
,
'-r'
,
revision
]
out
,
err
,
code
=
_hg_command
(
module
,
cmd2
)
if
code
==
1
:
raise
HgError
(
"There are unresolved files in
%
s"
%
dest
,
stderr
=
err
)
elif
code
==
0
:
# so far pull and update seems to be working, check revision and $revision are equal
_post_op_hg_revision_check
(
module
,
dest
,
revision
)
return
True
# when code aren't 1 or 0 in either command
raise
HgError
(
""
,
stderr
=
err
)
def
clone
(
module
,
repo
,
dest
,
revision
,
force
):
if
os
.
path
.
exists
(
dest
):
if
_hg_verify
(
module
,
dest
):
# make sure it's a real repo
if
_post_op_hg_revision_check
(
module
,
dest
,
revision
):
# make sure revision and $revision are equal
if
force
==
'yes'
:
force_and_clean
(
module
,
dest
)
return
False
cmd
=
[
'clone'
,
repo
,
dest
,
'-r'
,
revision
]
out
,
err
,
code
=
_hg_command
(
module
,
cmd
)
if
code
==
0
:
_hg_verify
(
module
,
dest
)
_post_op_hg_revision_check
(
module
,
dest
,
revision
)
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
:
raise
HgError
(
err
,
stderr
=
''
)
return
False
def
hg_pull
(
module
,
dest
,
revision
):
return
_hg_command
(
module
,
[
'pull'
,
'-r'
,
revision
,
'-R'
,
dest
])
def
hg_update
(
module
,
dest
,
revision
):
return
_hg_command
(
module
,
[
'update'
,
'-R'
,
dest
])
def
hg_clone
(
module
,
repo
,
dest
,
revision
):
return
_hg_command
(
module
,
[
'clone'
,
repo
,
dest
,
'-r'
,
revision
])
def
switch_version
(
module
,
dest
,
revision
):
return
_hg_command
(
module
,
[
'update'
,
'-r'
,
revision
,
'-R'
,
dest
])
# ===========================================
def
main
():
module
=
AnsibleModule
(
argument_spec
=
dict
(
repo
=
dict
(
required
=
True
),
dest
=
dict
(
required
=
True
),
state
=
dict
(
default
=
'present'
,
choices
=
[
'present'
,
'absent'
,
'latest'
]),
revision
=
dict
(
default
=
"default"
),
force
=
dict
(
default
=
'yes'
,
choices
=
[
'yes'
,
'no'
]),
purge
=
dict
(
default
=
'no'
,
choices
=
[
'yes'
,
'no'
])
),
)
repo
=
module
.
params
[
'repo'
]
state
=
module
.
params
[
'state'
]
dest
=
module
.
params
[
'dest'
]
revision
=
module
.
params
[
'revision'
]
force
=
module
.
params
[
'force'
]
force
=
module
.
boolean
(
module
.
params
[
'force'
])
purge
=
module
.
boolean
(
module
.
params
[
'purge'
])
hgrc
=
os
.
path
.
join
(
dest
,
'.hg/hgrc'
)
# initial states
before
=
''
changed
=
False
cleaned
=
False
# 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
)
if
rc
!=
0
:
module
.
fail_json
(
msg
=
err
)
else
:
# get the current state before doing pulling
before
=
get_revision
(
module
,
dest
)
# can perform force and purge
cleaned
=
hg_cleanup
(
module
,
dest
,
force
,
purge
)
(
rc
,
out
,
err
)
=
hg_pull
(
module
,
dest
,
revision
)
if
rc
!=
0
:
module
.
fail_json
(
msg
=
err
)
(
rc
,
out
,
err
)
=
hg_update
(
module
,
dest
,
revision
)
if
rc
!=
0
:
module
.
fail_json
(
msg
=
err
)
try
:
if
state
==
'absent'
:
if
not
os
.
path
.
exists
(
dest
):
shutil
.
rmtree
(
dest
)
switch_version
(
module
,
dest
,
revision
)
after
=
get_revision
(
module
,
dest
)
if
before
!=
after
or
cleaned
:
changed
=
True
elif
state
==
'present'
:
changed
=
clone
(
module
,
repo
,
dest
,
revision
,
force
)
elif
state
==
'latest'
:
changed
=
pull_and_update
(
module
,
repo
,
dest
,
revision
,
force
)
module
.
exit_json
(
dest
=
dest
,
changed
=
changed
)
except
Exception
as
e
:
module
.
fail_json
(
msg
=
str
(
e
),
params
=
module
.
params
)
module
.
exit_json
(
before
=
before
,
after
=
after
,
changed
=
changed
,
cleaned
=
cleaned
)
# include magic from lib/ansible/module_common.py
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment