11import os
22import sys
33import subprocess
4+ import shutil
45import re
56from pathlib import Path
67
2627}
2728"""
2829
29- # Define the repository URL (unchanged)
30- simple_repository_url = """maven {
31- url uri("${project.projectDir}/qct-gradle/configuration")
32- }
33- """
34- simple_repository_url_kts = """maven {
35- url = uri("${project.projectDir}/qct-gradle/configuration")
36- }
37- """
38- repository_url_groovy = """maven {
39- url uri("${project.projectDir}/qct-gradle/configuration")
40- metadataSources {
41- mavenPom()
42- artifact()
43- }
44- }
45- """
46-
47- repository_url_kts = """maven {
48- url = uri("${project.projectDir}/qct-gradle/configuration")
49- metadataSources {
50- mavenPom()
51- artifact()
52- }
53- }
54- """
55-
5630
5731run_build_env_copy_content = '''
5832import java.nio.file.Files
@@ -328,22 +302,270 @@ def destDir = file("$finalDir/caches/modules-2/files-2.1/")
328302'''
329303
330304custom_init_script_content = '''
305+
331306gradle.rootProject {
332307 task cacheToMavenLocal(type: Sync) {
333308 def destinationDirectory = "${project.projectDir}/qct-gradle/configuration"
334309 println(destinationDirectory)
310+
335311 from new File("${project.projectDir}/qct-gradle/START", "caches/modules-2/files-2.1")
336312 into destinationDirectory
313+
314+ duplicatesStrategy = DuplicatesStrategy.EXCLUDE // Choose the strategy that suits your needs
315+
337316 eachFile {
338317 List<String> parts = it.path.split('/')
339318 println(parts)
340- it.path = [parts[0].replace('.','/'), parts[1], parts[2], parts[4]].join('/')
319+ it.path = [parts[0].replace('.', '/'), parts[1], parts[2], parts[4]].join('/')
341320 }
321+
342322 includeEmptyDirs false
343323 }
324+
325+ }
326+ '''
327+
328+ full_download = '''
329+ // This is the init.gradle script
330+
331+ def resolveConfiguration = { config ->
332+ try {
333+ config.resolvedConfiguration.resolvedArtifacts.each { artifact ->
334+ println " - ${artifact.file.absolutePath}"
335+ }
336+ config.resolvedConfiguration.firstLevelModuleDependencies.each { dep ->
337+ resolveDependencies(dep)
338+ }
339+ } catch (Exception e) {
340+ println " Failed to resolve configuration: ${config.name}, reason: ${e.message}"
341+ }
342+ }
343+
344+ def resolveDependencies = { dep ->
345+ dep.children.each { childDep ->
346+ childDep.moduleArtifacts.each { artifact ->
347+ println " - ${artifact.file.absolutePath}"
348+ }
349+ resolveDependencies(childDep)
350+ }
351+ }
352+
353+ allprojects {
354+ afterEvaluate { project ->
355+ project.tasks.create("resolveAllConfigurations") {
356+ doLast {
357+ project.configurations.all { config ->
358+ println "Resolving configuration: ${config.name}"
359+ resolveConfiguration(config)
360+ }
361+ }
362+ }
363+
364+ project.tasks.create("resolveDetachedConfigurations") {
365+ doLast {
366+ def detachedConfigs = project.configurations.findAll { it.name.startsWith('detached') }
367+ detachedConfigs.each { config ->
368+ println "Resolving detached configuration: ${config.name}"
369+ resolveConfiguration(config)
370+ }
371+ }
372+ }
373+ }
344374}
375+
345376'''
346377
378+ def run_gradlew (project_dir ):
379+ try :
380+ subprocess .run (['./gradlew' , '-p' , project_dir ], check = True , cwd = project_dir )
381+ print ("gradlew command executed successfully." )
382+ except subprocess .CalledProcessError as e :
383+ print (f"An error occurred while running gradlew: { e } " )
384+ sys .exit (1 )
385+
386+ class GradleWrapperPropertiesManager :
387+ def __init__ (self , project_dir ):
388+ self .project_dir = project_dir
389+ self .properties_file = os .path .join (project_dir , 'gradle' , 'wrapper' , 'gradle-wrapper.properties' )
390+ self .original_values = {}
391+
392+ def _read_properties (self ):
393+ properties = {}
394+ with open (self .properties_file , 'r' ) as file :
395+ for line in file :
396+ if "=" in line :
397+ key , value = line .strip ().split ("=" , 1 )
398+ properties [key ] = value
399+ return properties
400+
401+ def _write_properties (self , properties ):
402+ with open (self .properties_file , 'w' ) as file :
403+ for key , value in properties .items ():
404+ file .write (f"{ key } ={ value } \n " )
405+
406+ def set_custom_distribution (self , distributionBase , distributionPath ):
407+ properties = self ._read_properties ()
408+ # Store original values if they exist
409+ self .original_values ['distributionBase' ] = properties .get ('distributionBase' , '' )
410+ self .original_values ['distributionPath' ] = properties .get ('distributionPath' , '' )
411+
412+ # Set custom values (create them if they don't exist)
413+ properties ['distributionBase' ] = distributionBase
414+ properties ['distributionPath' ] = distributionPath
415+ properties ['zipStoreBase' ] = distributionBase
416+ properties ['zipStorePath' ] = distributionPath
417+
418+ self ._write_properties (properties )
419+ print (f"Set custom distributionBase={ distributionBase } and distributionPath={ distributionPath } " )
420+
421+ def reset_distribution (self ):
422+ properties = self ._read_properties ()
423+ # Reset to original values
424+ if 'distributionBase' in self .original_values :
425+ properties ['distributionBase' ] = self .original_values .get ('distributionBase' , '' )
426+ if 'distributionPath' in self .original_values :
427+ properties ['distributionPath' ] = self .original_values .get ('distributionPath' , '' )
428+
429+ self ._write_properties (properties )
430+ print ("Reset distributionBase and distributionPath to original values" )
431+
432+ def modify_init_scripts (self , project_dir , distributionPath ):
433+ distribution_path_full = os .path .join (project_dir , distributionPath )
434+ if not os .path .exists (distribution_path_full ):
435+ print (f"The distribution path { distribution_path_full } does not exist." )
436+ return
437+
438+ for root , dirs , files in os .walk (distribution_path_full ):
439+ # Limit the depth to two levels
440+ if root [len (distribution_path_full ):].count (os .sep ) < 4 :
441+ print ("this is the root when we are walking: " + root )
442+ print ("this is the dirs when we are walking: " + str (dirs ))
443+ if 'init.d' in dirs :
444+ init_d_path = os .path .join (root , 'init.d' )
445+ print (init_d_path )
446+ for script_name in os .listdir (init_d_path ):
447+ print (script_name )
448+ if script_name .endswith ('.gradle' ):
449+ script_path = os .path .join (init_d_path , script_name )
450+ ScriptModifier (self .project_dir ).modify_script (script_path )
451+
452+ def zip_distribution (self , distributionPath , zip_file_name ):
453+ # Determine the full path to the distribution directory
454+ distribution_dir = os .path .join (self .project_dir , distributionPath )
455+
456+ # Make sure the directory exists
457+ if not os .path .exists (distribution_dir ):
458+ print (f"The distribution directory { distribution_dir } does not exist." )
459+ return
460+
461+ print (f"Starting traversal of { distribution_dir } ..." )
462+
463+ parent_dir_to_zip = None
464+
465+ # Traverse the directories under the distribution_dir
466+ for root , dirs , files in os .walk (distribution_dir ):
467+ print (f"Checking directory: { root } " )
468+ if 'init.d' in dirs and 'bin' in dirs :
469+ parent_dir_to_zip = root
470+ print (f"Found 'init.d' and 'bin' under: { root } " )
471+ break # Stop further traversal once the parent directory is found
472+ print (root )
473+ print (parent_dir_to_zip )
474+ if not parent_dir_to_zip :
475+ print ("Could not find a parent directory containing both 'init.d' and 'bin'." )
476+ return
477+
478+ # Define the output zip file path in gradle/wrapper directory
479+ output_zip = os .path .join (self .project_dir , 'gradle' , 'wrapper' , zip_file_name )
480+
481+ # Create a temporary directory to hold the parent directory as a subdir
482+ temp_dir = os .path .join (self .project_dir , 'temp_zip_dir' )
483+ if os .path .exists (temp_dir ):
484+ shutil .rmtree (temp_dir ) # Remove if it already exists
485+ os .makedirs (temp_dir )
486+
487+ # Move the parent directory into the temp directory
488+ subdir_name = os .path .basename (parent_dir_to_zip )
489+ shutil .copytree (parent_dir_to_zip , os .path .join (temp_dir , subdir_name ))
490+
491+ # Zip the temp directory, which now contains only the parent directory as a subdir
492+ shutil .make_archive (output_zip .replace ('.zip' , '' ), 'zip' , temp_dir )
493+ print (f"Zipped distribution directory { parent_dir_to_zip } as subdir to { output_zip } " )
494+
495+ # Clean up the temporary directory
496+ shutil .rmtree (temp_dir )
497+ print ("Cleaned up temporary directory." )
498+ def update_distribution_url (self , zip_file_name ):
499+ properties = self ._read_properties ()
500+ properties ['distributionUrl' ] = zip_file_name
501+ self ._write_properties (properties )
502+ print (f"Updated distributionUrl to point to { zip_file_name } " )
503+
504+ def check_update_url_is_public (self ):
505+ pattern = r"services\.gradle\.org\/distributions\/gradle-[\d\.]+-(bin|all)\.zip"
506+ properties = self ._read_properties ()
507+ distribution_url = properties .get ('distributionUrl' , '' )
508+ print ("this is the distribuition url, " , distribution_url )
509+ if re .search (pattern , distribution_url ):
510+ # If the pattern matches, update the distributionUrl
511+ self ._write_properties (properties )
512+ print (f"Found a public gradle distribution URL" )
513+ return True
514+ else :
515+ print ("The distributionUrl does not match the expected pattern." )
516+ return False
517+
518+
519+ class ScriptModifier :
520+ def __init__ (self , project_dir ):
521+ self .project_dir = project_dir
522+
523+ def modify_script (self , script_path ):
524+ local_path = "${rootProject.rootDir}/qct-gradle/configuration"
525+ with open (script_path , 'r' ) as file :
526+ script_content = file .read ()
527+
528+ # Modify the script content to add new maven{} entries within repos{} block
529+ modified_content = self .add_maven_repos (script_content , local_path )
530+ print ("this is the modified content" )
531+ with open (script_path , 'w' ) as file :
532+ file .write (modified_content )
533+
534+ print (f"Modified script at { script_path } to use local path { local_path } " )
535+
536+ def add_maven_repos (self , content , local_path ):
537+ new_maven_repo = f"""
538+ maven {{
539+ url '{ local_path } '
540+ metadataSources {{
541+ mavenPom()
542+ artifact()
543+ }}
544+ }}
545+ """
546+
547+ # Find the repositories block manually and modify it
548+ start_idx = content .find ('repositories {' )
549+ if start_idx == - 1 :
550+ # If no repositories block is found, return the content as is
551+ return content
552+
553+ # Find the matching closing brace for the repositories block
554+ open_braces = 1
555+ end_idx = start_idx + len ('repositories {' )
556+ while open_braces > 0 and end_idx < len (content ):
557+ if content [end_idx ] == '{' :
558+ open_braces += 1
559+ elif content [end_idx ] == '}' :
560+ open_braces -= 1
561+ end_idx += 1
562+
563+ # Insert the new maven repository before the closing brace
564+ modified_repositories_block = content [start_idx :end_idx - 1 ].strip () + f"\n { new_maven_repo .strip ()} \n " + content [end_idx - 1 :end_idx ]
565+
566+ # Replace the old block with the modified one
567+ return content [:start_idx ] + modified_repositories_block + content [end_idx :]
568+
347569def create_init_script (directory , init_name , content ):
348570 qct_gradle_dir = os .path .join (directory , 'qct-gradle' )
349571 os .makedirs (qct_gradle_dir , exist_ok = True )
@@ -369,7 +591,7 @@ def run_gradle_task(init_script_path, directory_path, task):
369591 try :
370592 result = subprocess .run ([f"{ directory_path } /gradlew" , task , '--init-script' , init_script_path , '-g' , f"{ directory_path } /qct-gradle/START" , '-p' , f"{ directory_path } " , '--info' ], check = True , text = True , capture_output = True )
371593 except Exception as e :
372- print (f'task failed: { task } ' )
594+ print (f'this was this task that failed: { task } ' )
373595 print (f'e.stdout = { e .stdout } ' )
374596 print (f'e.stderr = { e .stderr } ' )
375597 print (f'e.returncode = { e .returncode } ' )
@@ -404,6 +626,7 @@ def run(directory_path):
404626 except Exception as e :
405627 print (f"Error making gradlew executable, going to continue anyway: { e } " )
406628 else :
629+ # TO-DO: get text approved
407630 print ("gradlew executable not found. Please ensure you have a Gradle wrapper at the root of your project. Run 'gradle wrapper' to generate one." )
408631 sys .exit (1 )
409632 try :
@@ -418,6 +641,40 @@ def run(directory_path):
418641 print (f"An error occurred: { e } " )
419642 sys .exit (1 )
420643
644+ def run_properties (dir ,action_1 , distBase , distPath , zip_name ):
645+
646+ project_directory = dir
647+ action = action_1
648+
649+ manager = GradleWrapperPropertiesManager (project_directory )
650+
651+ if action == 'set' and not manager .check_update_url_is_public ():
652+ distributionBase = distBase
653+ distributionPath = distPath
654+ zip_file_name = zip_name
655+
656+ #modify the properites of the gradle wrapper
657+ manager .set_custom_distribution (distributionBase , distributionPath )
658+
659+ #do a gradlew to pull the artifacts to the specified destination
660+ run_gradlew (project_directory )
661+
662+ #modify the initialization scripts under init.d
663+ manager .modify_init_scripts (project_directory , distributionPath )
664+
665+ # Zip the custom distribution
666+ manager .zip_distribution ( distributionPath , zip_file_name )
667+
668+ # Update the gradle-wrapper.properties file to point to the new zip file
669+ manager .update_distribution_url (zip_file_name )
670+
671+ print ("DONE" )
672+ elif action == 'reset' :
673+ manager .reset_distribution ()
674+ else :
675+ print ("Unknown action. Use 'set' to set custom distribution or 'reset' to reset to original values." )
676+
677+
421678if __name__ == "__main__" :
422679 if len (sys .argv ) != 2 :
423680 # should never happen because script is invoked correctly from toolkit
@@ -426,4 +683,8 @@ def run(directory_path):
426683 sys .exit (1 ) # set return code to non-zero value
427684 else :
428685 directory_path = sys .argv [1 ]
686+ distBase = 'PROJECT'
687+ disPath = 'custom-wrapper/dists'
688+ zipPath = 'customDist.zip'
429689 run (directory_path )
690+ run_properties (directory_path , "set" , distBase , disPath , zipPath )
0 commit comments