1
1
import os
2
+ import re
2
3
import subprocess
3
4
import logging
4
5
import time
5
6
import argparse
6
7
import datetime
7
- from traitlets import Integer , default
8
+ from traitlets import Bool , CRegExp , Integer , List , Unicode , Union , default
8
9
from traitlets .config import Configurable
9
10
from functools import partial
10
11
@@ -49,6 +50,33 @@ def flush():
49
50
50
51
51
52
class GitPuller (Configurable ):
53
+ autorun_allow = Union (
54
+ [List (CRegExp ()), Bool ()],
55
+ default_value = False ,
56
+ config = True ,
57
+ help = """
58
+ List of URLs described as Python regular expressions (using re.fullmatch()) where
59
+ it is permitted to autorun scripts from the pulled project as a pre-initialisation
60
+ step. Enable this only if you understand and accept the risks of AUTORUN.INF.
61
+
62
+ When set to boolean True, all URLs are allowed, whilst False (default) autorun
63
+ is disabled completely.
64
+ """
65
+ )
66
+
67
+ autorun_script = List (
68
+ Unicode (),
69
+ default_value = [],
70
+ config = True ,
71
+ help = """
72
+ List of scripts to search for when attempting to autorun. The first match will
73
+ be run with a single argument of 'init' or 'update' depending on what nbgitpuller
74
+ is doing.
75
+
76
+ Enable this only if you understand and accept the risks of AUTORUN.INF.
77
+ """
78
+ )
79
+
52
80
depth = Integer (
53
81
config = True ,
54
82
help = """
@@ -143,6 +171,25 @@ def pull(self):
143
171
else :
144
172
yield from self .update ()
145
173
174
+ def autorun (self , operation = "method" ):
175
+ """
176
+ Search for and execute the autorun script.
177
+ """
178
+
179
+ if not self .autorun_allow :
180
+ return
181
+ if not any (( re .fullmatch (pattern , self .git_url ) for pattern in self .autorun_allow )):
182
+ logging .info ('autorun skipped, URL does not match any rules' )
183
+ return
184
+
185
+ script = next (( s for s in self ._autorun_script if os .path .exists (os .path .join (self .repo_dir , s )) ), None )
186
+ if not script :
187
+ logging .info ('autorun skipped, no matching script' )
188
+ return
189
+
190
+ logging .info ('autorun executing: %s %s' , script , operation )
191
+ yield from execute_cmd ([ script , operation ], cwd = self .repo_dir , shell = True )
192
+
146
193
def initialize_repo (self ):
147
194
"""
148
195
Clones repository
@@ -154,6 +201,7 @@ def initialize_repo(self):
154
201
clone_args .extend (['--branch' , self .branch_name ])
155
202
clone_args .extend (["--" , self .git_url , self .repo_dir ])
156
203
yield from execute_cmd (clone_args )
204
+ self .autorun ('init' )
157
205
logging .info ('Repo {} initialized' .format (self .repo_dir ))
158
206
159
207
def reset_deleted_files (self ):
@@ -343,6 +391,7 @@ def update(self):
343
391
yield from self .ensure_lock ()
344
392
yield from self .merge ()
345
393
394
+ self .autorun ('update' )
346
395
347
396
def main ():
348
397
"""
0 commit comments