Skip to content

Commit

Permalink
BF: do not install post-update hook if no UI, allow to reconfigure fu…
Browse files Browse the repository at this point in the history
…ll hierarchy, no submodule update --init in hook (#3318)

Merge pull request #3318 from yarikoptic/bf-nopostupdate-if-no-ui
  • Loading branch information
yarikoptic committed Apr 12, 2019
2 parents 39e8e8b + 01cf595 commit ab64a6c
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 73 deletions.
117 changes: 88 additions & 29 deletions datalad/distribution/create_sibling.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ def _create_dataset_sibling(
group,
publish_depends,
publish_by_default,
install_postupdate_hook,
as_common_datasrc,
annex_wanted,
annex_group,
Expand Down Expand Up @@ -196,12 +197,22 @@ def _create_dataset_sibling(
if not path_exists:
ssh("mkdir -p {}".format(sh_quote(remoteds_path)))

if inherit and shared is None:
# here we must analyze current_ds's super, not the super_ds
delayed_super = _DelayedSuper(ds)
# inherit from the setting on remote end
shared = CreateSibling._get_ds_remote_shared_setting(
delayed_super, name, ssh)
delayed_super = _DelayedSuper(ds)
if inherit and delayed_super.super:
if shared is None:
# here we must analyze current_ds's super, not the super_ds
# inherit from the setting on remote end
shared = CreateSibling._get_ds_remote_shared_setting(
delayed_super, name, ssh)

if not install_postupdate_hook:
# Even though directive from above was False due to no UI explicitly
# requested, we were asked to inherit the setup, so we might need
# to install the hook, if super has it on remote
install_postupdate_hook = CreateSibling._has_active_postupdate(
delayed_super, name, ssh)



if group:
# Either repository existed before or a new directory was created for it,
Expand Down Expand Up @@ -265,14 +276,15 @@ def _create_dataset_sibling(
" and run with --existing=reconfigure",
ssh.get_git_version())

# enable metadata refresh on dataset updates to publication server
lgr.info("Enabling git post-update hook ...")
try:
CreateSibling.create_postupdate_hook(
remoteds_path, ssh, ds)
except CommandError as e:
lgr.error("Failed to add json creation command to post update "
"hook.\nError: %s" % exc_str(e))
if install_postupdate_hook:
# enable metadata refresh on dataset updates to publication server
lgr.info("Enabling git post-update hook ...")
try:
CreateSibling.create_postupdate_hook(
remoteds_path, ssh, ds)
except CommandError as e:
lgr.error("Failed to add json creation command to post update "
"hook.\nError: %s" % exc_str(e))

return remoteds_path

Expand Down Expand Up @@ -608,6 +620,7 @@ def __call__(sshurl, name=None, target_dir=None,
group,
publish_depends,
publish_by_default,
ui,
as_common_datasrc,
annex_wanted,
annex_group,
Expand Down Expand Up @@ -643,10 +656,11 @@ def __call__(sshurl, name=None, target_dir=None,
# TODO: add progressbar
for path, currentds_ap in remote_repos_to_run_hook_for[::-1]:
# Trigger the hook
lgr.debug("Running hook for %s", path)
lgr.debug("Running hook for %s (if exists and executable)", path)
try:
ssh("cd {} && hooks/post-update".format(
sh_quote(_path_(path, ".git"))))
ssh("cd {} "
"&& ( [ -x hooks/post-update ] && hooks/post-update || : )"
"".format(sh_quote(_path_(path, ".git"))))
except CommandError as e:
currentds_ap['status'] = 'error'
currentds_ap['message'] = (
Expand All @@ -660,22 +674,42 @@ def __call__(sshurl, name=None, target_dir=None,
currentds_ap['status'] = 'ok'
yield currentds_ap

@staticmethod
def _run_on_ds_ssh_remote(ds, name, ssh, cmd):
"""Given a dataset, and name of the remote, run command via ssh
Parameters
----------
cmd: str
Will be .format()'ed given the `path` to the dataset on remote
Returns
-------
out
Raises
------
CommandError
"""
remote_url = CreateSibling._get_remote_url(ds, name)
remote_ri = RI(remote_url)
out, err = ssh(cmd.format(path=sh_quote(remote_ri.path)))
if err:
lgr.warning("Got stderr while calling ssh: %s", err)
return out

@staticmethod
def _get_ds_remote_shared_setting(ds, name, ssh):
"""Figure out setting of sharedrepository for dataset's `name` remote"""
shared = None
try:
current_super_url = CreateSibling._get_remote_url(
ds, name)
current_super_ri = RI(current_super_url)
out, err = ssh('git -C {} config --get core.sharedrepository'.format(
# TODO -- we might need to expanduser taking .user into account
# but then it must be done also on remote side
sh_quote(current_super_ri.path))
# TODO -- we might need to expanduser taking .user into account
# but then it must be done also on remote side
out = CreateSibling._run_on_ds_ssh_remote(
ds, name, ssh,
'git -C {path} config --get core.sharedrepository'
)
shared = out.strip()
if err:
lgr.warning("Got stderr while calling ssh: %s", err)
except CommandError as e:
lgr.debug(
"Could not figure out remote shared setting of %s for %s due "
Expand All @@ -686,6 +720,34 @@ def _get_ds_remote_shared_setting(ds, name, ssh):
# TODO: more detailed analysis may be?
return shared

@staticmethod
def _has_active_postupdate(ds, name, ssh):
"""Figure out either has active post-update hook
Returns
-------
bool or None
None if something went wrong and we could not figure out
"""
has_active_post_update = None
try:
# TODO -- we might need to expanduser taking .user into account
# but then it must be done also on remote side
out = CreateSibling._run_on_ds_ssh_remote(
ds, name, ssh,
'cd {path} && [ -x .git/hooks/post-update ] && echo yes || echo no'
)
out = out.strip()
assert out in ('yes', 'no')
has_active_post_update = out == "yes"
except CommandError as e:
lgr.debug(
"Could not figure out either %s on remote %s has active "
"post_update hook due to %s",
ds, name, exc_str(e)
)
return has_active_post_update

@staticmethod
def _get_remote_url(ds, name):
"""A little helper to get url from pushurl or from url if not defined"""
Expand Down Expand Up @@ -757,9 +819,6 @@ def create_postupdate_hook(path, ssh, dataset):
&& ( cd "$dsdir"; GIT_DIR="$PWD/.git" datalad ls -a --json file .; ) \
|| echo "E: no datalad found - skipping generation of indexes for web frontend"; \
) &> "$logfile"
# Some submodules might have been added and thus we better init them
( cd "$dsdir"; git submodule update --init || : ; ) >> "$logfile" 2>&1
'''.format(WEB_META_LOG=WEB_META_LOG, **locals())

with make_tempfile(content=hook_content) as tempf:
Expand Down
19 changes: 11 additions & 8 deletions datalad/distribution/siblings.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,9 +439,9 @@ def _configure_remote(
r.update(res_kwargs)
yield r

if inherit:
delayed_super = _DelayedSuper(ds.repo)
if inherit and delayed_super.super is not None:
# Adjust variables which we should inherit
delayed_super = _DelayedSuper(ds.repo)
publish_depends = _inherit_config_var(
delayed_super, depvar, publish_depends)
publish_by_default = _inherit_config_var(
Expand Down Expand Up @@ -812,33 +812,36 @@ def _inherit_config_var(ds, cfgvar, var):
class _DelayedSuper(object):
"""A helper to delay deduction on super dataset until needed
But if asked and not found -- blow up
But if asked and not found -- would return None for everything
"""

def __init__(self, repo):
self._child_dataset = Dataset(repo.path)
self._super = None
self._super_tried = False

def __str__(self):
return str(self.super)

@property
def super(self):
if self._super is None:
if not self._super_tried:
self._super_tried = True
# here we must analyze current_ds's super, not the super_ds
self._super = self._child_dataset.get_superdataset()
if not self._super:
raise RuntimeError(
lgr.warning(
"Cannot determine super dataset for %s, thus "
"cannot inherit anything" % self._child_dataset
"probably nothing would be inherited where desired"
% self._child_dataset
)
return self._super

# Lean proxies going through .super
@property
def config(self):
return self.super.config
return self.super.config if self.super else None

@property
def repo(self):
return self.super.repo
return self.super.repo if self.super else None
Loading

0 comments on commit ab64a6c

Please sign in to comment.