60
60
from easybuild .tools .filetools import find_easyconfigs , is_patch_file , locate_files
61
61
from easybuild .tools .filetools import read_file , resolve_path , which , write_file
62
62
from easybuild .tools .github import GITHUB_EASYCONFIGS_REPO
63
- from easybuild .tools .github import det_pr_labels , det_pr_title , download_repo , fetch_easyconfigs_from_pr , fetch_pr_data
64
- from easybuild .tools .github import fetch_files_from_pr
63
+ from easybuild .tools .github import det_pr_labels , det_pr_title , download_repo , fetch_easyconfigs_from_commit
64
+ from easybuild .tools .github import fetch_easyconfigs_from_pr , fetch_pr_data
65
+ from easybuild .tools .github import fetch_files_from_commit , fetch_files_from_pr
65
66
from easybuild .tools .multidiff import multidiff
66
67
from easybuild .tools .py2vs3 import OrderedDict
67
68
from easybuild .tools .toolchain .toolchain import is_system_toolchain
@@ -310,7 +311,7 @@ def get_paths_for(subdir=EASYCONFIGS_PKG_SUBDIR, robot_path=None):
310
311
return paths
311
312
312
313
313
- def alt_easyconfig_paths (tmpdir , tweaked_ecs = False , from_prs = None , review_pr = None ):
314
+ def alt_easyconfig_paths (tmpdir , tweaked_ecs = False , from_prs = None , from_commit = None , review_pr = None ):
314
315
"""Obtain alternative paths for easyconfig files."""
315
316
316
317
# paths where tweaked easyconfigs will be placed, easyconfigs listed on the command line take priority and will be
@@ -321,18 +322,20 @@ def alt_easyconfig_paths(tmpdir, tweaked_ecs=False, from_prs=None, review_pr=Non
321
322
tweaked_ecs_paths = (os .path .join (tmpdir , 'tweaked_easyconfigs' ),
322
323
os .path .join (tmpdir , 'tweaked_dep_easyconfigs' ))
323
324
324
- # paths where files touched in PRs will be downloaded to,
325
- # which are picked up via 'pr_paths ' build option in fetch_files_from_pr
326
- pr_paths = []
325
+ # paths where files touched in commit/ PRs will be downloaded to,
326
+ # which are picked up via 'extra_ec_paths ' build option in fetch_files_from_pr
327
+ extra_ec_paths = []
327
328
if from_prs :
328
- pr_paths = from_prs [:]
329
- if review_pr and review_pr not in pr_paths :
330
- pr_paths .append (review_pr )
329
+ extra_ec_paths = from_prs [:]
330
+ if review_pr and review_pr not in extra_ec_paths :
331
+ extra_ec_paths .append (review_pr )
332
+ if extra_ec_paths :
333
+ extra_ec_paths = [os .path .join (tmpdir , 'files_pr%s' % pr ) for pr in extra_ec_paths ]
331
334
332
- if pr_paths :
333
- pr_paths = [ os .path .join (tmpdir , 'files_pr%s' % pr ) for pr in pr_paths ]
335
+ if from_commit :
336
+ extra_ec_paths . append ( os .path .join (tmpdir , 'files_commit_' + from_commit ))
334
337
335
- return tweaked_ecs_paths , pr_paths
338
+ return tweaked_ecs_paths , extra_ec_paths
336
339
337
340
338
341
def det_easyconfig_paths (orig_paths ):
@@ -346,27 +349,31 @@ def det_easyconfig_paths(orig_paths):
346
349
except ValueError :
347
350
raise EasyBuildError ("Argument to --from-pr must be a comma separated list of PR #s." )
348
351
352
+ from_commit = build_option ('from_commit' )
349
353
robot_path = build_option ('robot_path' )
350
354
351
355
# list of specified easyconfig files
352
356
ec_files = orig_paths [:]
353
357
358
+ commit_files , pr_files = [], []
354
359
if from_prs :
355
- pr_files = []
356
360
for pr in from_prs :
357
- # path to where easyconfig files should be downloaded is determined via 'pr_paths' build option,
358
- # which corresponds to the list of PR paths returned by alt_easyconfig_paths
361
+ # path to where easyconfig files should be downloaded is determined
362
+ # via 'extra_ec_paths' build options,
363
+ # which corresponds to the list of commit/PR paths returned by alt_easyconfig_paths
359
364
pr_files .extend (fetch_easyconfigs_from_pr (pr ))
360
-
361
- if ec_files :
362
- # replace paths for specified easyconfigs that are touched in PR
363
- for i , ec_file in enumerate (ec_files ):
364
- for pr_file in pr_files :
365
- if ec_file == os .path .basename (pr_file ):
366
- ec_files [i ] = pr_file
367
- else :
368
- # if no easyconfigs are specified, use all the ones touched in the PR
369
- ec_files = [path for path in pr_files if path .endswith ('.eb' )]
365
+ elif from_commit :
366
+ commit_files = fetch_easyconfigs_from_commit (from_commit , files = ec_files )
367
+
368
+ if ec_files :
369
+ # replace paths for specified easyconfigs that are touched in commit/PRs
370
+ for i , ec_file in enumerate (ec_files ):
371
+ for file in commit_files + pr_files :
372
+ if ec_file == os .path .basename (file ):
373
+ ec_files [i ] = file
374
+ else :
375
+ # if no easyconfigs are specified, use all the ones touched in the commit/PRs
376
+ ec_files = [path for path in commit_files + pr_files if path .endswith ('.eb' )]
370
377
371
378
filter_ecs = build_option ('filter_ecs' )
372
379
if filter_ecs :
@@ -784,7 +791,7 @@ def avail_easyblocks():
784
791
return easyblocks
785
792
786
793
787
- def det_copy_ec_specs (orig_paths , from_pr ):
794
+ def det_copy_ec_specs (orig_paths , from_pr = None , from_commit = None ):
788
795
"""Determine list of paths + target directory for --copy-ec."""
789
796
790
797
if from_pr is not None and not isinstance (from_pr , list ):
@@ -848,4 +855,41 @@ def det_copy_ec_specs(orig_paths, from_pr):
848
855
elif pr_matches :
849
856
raise EasyBuildError ("Found multiple paths for %s in PR: %s" , filename , pr_matches )
850
857
858
+ # consider --from-commit (only if --from-pr was not used)
859
+ elif from_commit :
860
+ tmpdir = os .path .join (tempfile .gettempdir (), 'fetch_files_from_commit_%s' % from_commit )
861
+ commit_paths = fetch_files_from_commit (from_commit , path = tmpdir )
862
+
863
+ # assume that files need to be copied to current working directory for now
864
+ target_path = os .getcwd ()
865
+
866
+ if orig_paths :
867
+ last_path = orig_paths [- 1 ]
868
+
869
+ # check files touched by commit and see if the target directory for --copy-ec
870
+ # corresponds to the name of one of these files;
871
+ # if so we should copy the specified file(s) to the current working directory,
872
+ # since interpreting the last argument as target location is very unlikely to be correct in this case
873
+ commit_filenames = [os .path .basename (p ) for p in commit_paths ]
874
+ if last_path in commit_filenames :
875
+ paths = orig_paths [:]
876
+ else :
877
+ target_path = last_path
878
+ # exclude last argument that is used as target location
879
+ paths = orig_paths [:- 1 ]
880
+
881
+ # if list of files to copy is empty at this point,
882
+ # we simply copy *all* files touched by the PR
883
+ if not paths :
884
+ paths = commit_paths
885
+
886
+ # replace path for files touched by commit (no need to worry about others)
887
+ for idx , path in enumerate (paths ):
888
+ filename = os .path .basename (path )
889
+ commit_matches = [x for x in commit_paths if os .path .basename (x ) == filename ]
890
+ if len (commit_matches ) == 1 :
891
+ paths [idx ] = commit_matches [0 ]
892
+ elif commit_matches :
893
+ raise EasyBuildError ("Found multiple paths for %s in commit: %s" , filename , commit_matches )
894
+
851
895
return paths , target_path
0 commit comments