From 201d089445dfb5f0ddbe933a662221c46c5daba2 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Wed, 22 Feb 2023 08:26:46 +0000 Subject: [PATCH] autorun support disabled by default, and configurable via trailets --- nbgitpuller/pull.py | 49 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/nbgitpuller/pull.py b/nbgitpuller/pull.py index f5a7dab1..1e52ca39 100644 --- a/nbgitpuller/pull.py +++ b/nbgitpuller/pull.py @@ -1,10 +1,11 @@ import os +import re import subprocess import logging import time import argparse import datetime -from traitlets import Integer, default +from traitlets import Bool, CRegExp, Integer, List, Unicode, Union, default from traitlets.config import Configurable from functools import partial @@ -49,6 +50,33 @@ def flush(): class GitPuller(Configurable): + autorun_allow = Union( + [List(CRegExp()), Bool()], + default_value=False, + config=True, + help=""" + List of URLs described as Python regular expressions (using re.match()) where it + is permitted to autorun scripts from the pulled project as a pre-initialisation + step. Enable this only if you understand and accept the risks of AUTORUN.INF. + + When set to boolean True, all URLs are allowed, whilst False (default) autorun + is disabled completely. + """ + ) + + autorun_script = List( + Unicode(), + default_value=[], + config=True, + help=""" + List of scripts to search for when attempting to autorun. The first match will + be run with a single argument of 'init' or 'update' depending on what nbgitpuller + is doing. + + Enable this only if you understand and accept the risks of AUTORUN.INF. + """ + ) + depth = Integer( config=True, help=""" @@ -143,6 +171,23 @@ def pull(self): else: yield from self.update() + def autorun(self, operation="method"): + """ + Search for and execute the autorun script. + """ + + if not self.autorun_allow: + return + if not any(( re.match(pattern, self.git_url) for pattern in self.autorun_allow )): + return + + script = next(( s for s in self._autorun_script if os.path.exists(os.path.join(self.repo_dir, s)) ), None) + if not script: + return + + logging.info('Running "%s" %s', script, operation) + yield from execute_cmd([ script, operation ], cwd=self.repo_dir, shell=True) + def initialize_repo(self): """ Clones repository @@ -154,6 +199,7 @@ def initialize_repo(self): clone_args.extend(['--branch', self.branch_name]) clone_args.extend(["--", self.git_url, self.repo_dir]) yield from execute_cmd(clone_args) + self.autorun('init') logging.info('Repo {} initialized'.format(self.repo_dir)) def reset_deleted_files(self): @@ -343,6 +389,7 @@ def update(self): yield from self.ensure_lock() yield from self.merge() + self.autorun('update') def main(): """