@@ -8,66 +8,149 @@ import org.apache.hc.client5.http.impl.classic.HttpClients
88import org.apache.hc.core5.http.HttpStatus
99import org.gradle.api.DefaultTask
1010import org.gradle.api.GradleException
11- import org.gradle.api.Project
11+ import org.gradle.api.provider.Property
12+ import org.gradle.api.tasks.Input
13+ import org.gradle.api.tasks.Optional
1214import org.gradle.api.tasks.TaskAction
13- import org.labkey.gradle.plugin.Api
14- import org.labkey.gradle.plugin.FileModule
15- import org.labkey.gradle.plugin.JavaModule
16- import org.labkey.gradle.plugin.Module
17- import org.labkey.gradle.util.BuildUtils
15+ import org.labkey.gradle.util.TaskUtils
1816
1917import static org.labkey.gradle.task.PurgeArtifacts.Response
2018
21- // TODO for more flexibility and for configuration cache support, needs to be converted to read projects and versions
22- // from a file, as for PurgeArtifacts
2319class RestoreFromTrash extends DefaultTask
2420{
2521 public static final String VERSION_PROPERTY = " restoreVersion"
22+ public static final String VERSIONS_FILE_PROPERTY = ' restoreVersions'
23+ public static final String RESTORE_LIST_FILE_PROPERTY = ' restoreList' ;
24+
25+ @Input @Optional
26+ final abstract Property<String > restoreVersion = project. objects. property(String ). convention(project. hasProperty(VERSION_PROPERTY ) ? (String ) project. property(VERSION_PROPERTY ) : " " )
27+
28+ @Input @Optional
29+ final abstract Property<String > restoreVersions = project. objects. property(String ). convention(project. hasProperty(VERSIONS_FILE_PROPERTY ) ? (String ) project. property(VERSIONS_FILE_PROPERTY ) : " " )
30+ @Input @Optional
31+ final abstract Property<String > restoreListFile = project. objects. property(String ). convention(project. hasProperty(RESTORE_LIST_FILE_PROPERTY ) ? (String ) project. property(RESTORE_LIST_FILE_PROPERTY ) : " " )
32+ @Input
33+ final abstract Property<Boolean > isDryRun = project. objects. property(Boolean ). convention(project. hasProperty(PurgeArtifacts . DRY_RUN_PROPERTY ))
34+
35+ @Input
36+ final abstract Property<String > artifactoryUrl = project. objects. property(String ). convention((String ) project. property(' artifactory_contextUrl' ))
37+ @Input
38+ final abstract Property<String > artifactoryUser = project. objects. property(String ). convention((String ) project. property(' artifactory_user' ))
39+ @Input
40+ final abstract Property<String > artifactoryPassword = project. objects. property(String ). convention((String ) project. property(' artifactory_password' ))
41+
42+ private static final String NUM_NOT_FOUND = " numNotFound"
43+ private static final String NUM_RESTORED = " numRestored"
44+ private static final String UNRESTORED_VERSIONS = " unrestoredVersions"
2645
2746 @TaskAction
2847 void restoreVersions ()
2948 {
30- String restoreVersion
31- if (! project. hasProperty(VERSION_PROPERTY ))
32- throw new GradleException (" No value provided for ${ VERSION_PROPERTY} ." )
33- restoreVersion = project. property(VERSION_PROPERTY )
34- String [] unrestoredVersions = []
35- int numRestored = 0
36- int numNotFound = 0
37- project. allprojects({ Project p ->
38- def plugins = p. getPlugins()
39- if (plugins. hasPlugin(Module . class) || plugins. hasPlugin(JavaModule . class) || plugins. hasPlugin(FileModule . class)) {
40- logger. quiet(" Considering ${ p.path} ..." )
41- Response response = makeRestoreRequest(p. name, restoreVersion, " module" )
42- if (response == Response . NOT_FOUND )
43- numNotFound++
44- else if (response == Response . ERROR ) {
45- unrestoredVersions + = " ${ p.path} - module: ${ restoreVersion} "
46- } else
47- numRestored++
49+ String restoreModulesFileName = restoreListFile. get();
50+ if (StringUtils . isEmpty(restoreModulesFileName))
51+ throw new GradleException (" Use -P${ RESTORE_LIST_FILE_PROPERTY} =<moduleNames.txt> to provide a list of modules to work with." )
52+ List<String > moduleNames = TaskUtils . readInputFile(restoreModulesFileName, " modules" , logger)
53+ if (moduleNames. isEmpty())
54+ throw new GradleException (" No module names found in file ${ restoreModulesFileName} " )
55+ String version = this . restoreVersion. get()
56+ if (! StringUtils . isEmpty(version. trim()))
57+ this . restoreVersion(version, moduleNames)
58+ else
59+ {
60+ Map<String , Integer > overallStats = new HashMap<> ()
61+ overallStats. put(NUM_NOT_FOUND , 0 )
62+ overallStats. put(NUM_RESTORED , 0 )
63+ String restoreVersionsFileName = restoreVersions. get()
64+ if (StringUtils . isEmpty(restoreVersionsFileName))
65+ throw new GradleException (" Either -P${ VERSION_PROPERTY} =<versionToPurge> or -P${ VERSIONS_FILE_PROPERTY} =<versionsFile.txt> must be provided" )
66+ List<String > versions = TaskUtils . readInputFile(restoreVersionsFileName, " versions" , logger)
67+ if (versions. isEmpty())
68+ throw new GradleException (" No versions found for file ${ restoreVersionsFileName} ." )
69+ if (versions. size() > 1 ) {
70+ for (String moduleName : moduleNames) {
71+ Map<String , Object > restoreStats = restoreModuleVersions(moduleName, versions)
72+ overallStats. put(NUM_NOT_FOUND , overallStats. get(NUM_NOT_FOUND ) + (Integer ) restoreStats. get(NUM_NOT_FOUND ))
73+ overallStats. put(NUM_RESTORED , overallStats. get(NUM_RESTORED ) + (Integer ) restoreStats. get(NUM_RESTORED ))
74+ }
75+ if (moduleNames. size() > 1 )
76+ logger. quiet(" \n Summary:\n\t Restored ${ overallStats.get(NUM_RESTORED)} artifacts.\n\t ${ overallStats.get(NUM_NOT_FOUND)} artifacts not found." )
4877 }
49- if (plugins. hasPlugin(Api . class) || project. path == BuildUtils . getApiProjectPath(project. gradle)) {
50- Response response = makeRestoreRequest(p. name, restoreVersion, " api" )
51- if (response == Response . NOT_FOUND )
52- numNotFound++
53- else if (response == Response . ERROR ) {
54- unrestoredVersions + = " ${ p.path} - api: ${ restoreVersion} "
55- } else
56- numRestored++
78+ else {
79+ for (String v : versions) {
80+ if (! StringUtils . isEmpty(v. trim()))
81+ this . restoreVersion(v, moduleNames)
82+ }
5783 }
58- })
84+ }
85+ }
86+
87+ Map<String , Object > restoreModuleVersions (String moduleName , List<String > versions )
88+ {
89+ Map<String , Object > restoreStats = new HashMap ();
90+ restoreStats. put(NUM_RESTORED , 0 )
91+ restoreStats. put(NUM_NOT_FOUND , 0 )
92+ restoreStats. put(UNRESTORED_VERSIONS , new ArrayList<> ())
93+
94+ logger. quiet(" ### Begin restore for module ${ moduleName} for ${ versions.size()} versions\n " )
95+
96+ for (String version : versions) {
97+ if (! StringUtils . isEmpty(version. trim()))
98+ makeRequests(moduleName, moduleName, version, restoreStats)
99+ }
100+ logStats(restoreStats)
101+ logger. quiet(" \n ### End restore for module ${ moduleName} \n " )
102+ return restoreStats
103+ }
104+
105+ Map<String , Object > restoreVersion (String version , List<String > moduleNames )
106+ {
107+ if (StringUtils . isEmpty(version. trim()))
108+ return
109+ Map<String , Object > restoreStats = new HashMap ();
110+ restoreStats. put(NUM_RESTORED , 0 )
111+ restoreStats. put(NUM_NOT_FOUND , 0 )
112+ restoreStats. put(UNRESTORED_VERSIONS , new ArrayList<> ())
113+ for (String moduleName : moduleNames) {
114+ makeRequests(moduleName, moduleName, version, restoreStats)
115+ }
116+ logStats(restoreStats)
117+ return restoreStats
118+ }
59119
60- logger. quiet(" Restored ${ numRestored} artifacts; ${ numNotFound} artifacts not found." )
61- if (unrestoredVersions. size() > 0 && ! project. hasProperty(" dryRun" ))
62- throw new GradleException (" The following ${ unrestoredVersions.size()} versions were not restored.\n ${ StringUtils.join(unrestoredVersions, "\n")} \n Check the log for more information." )
120+ void logStats (Map<String , Object > restoreStats )
121+ {
122+ logger. quiet(" Restored ${ restoreStats.get(NUM_RESTORED)} artifacts; ${ restoreStats.get(NUM_NOT_FOUND)} artifacts not found." )
123+ if (((List<String > ) restoreStats. get(UNRESTORED_VERSIONS )). size() > 0 && ! isDryRun. get())
124+ throw new GradleException (" The following ${ ((List<String>) restoreStats.get(UNRESTORED_VERSIONS)).size()} versions were not restored.\n ${ StringUtils.join(restoreStats.get(UNRESTORED_VERSIONS), "\n")} \n Check the log for more information." )
125+ }
126+
127+ void makeRequests (String moduleName , String loggingName , String restoreVersion , Map<String , Object > statsMap )
128+ {
129+ if (StringUtils . isEmpty(restoreVersion. trim()))
130+ return
131+ logger. quiet(" Considering ${ loggingName} ${ restoreVersion} ..." )
132+ Response response = makeRestoreRequest(moduleName, restoreVersion, " module" )
133+ if (response == Response . NOT_FOUND )
134+ statsMap. put(NUM_NOT_FOUND , statsMap. get(NUM_NOT_FOUND )+1 );
135+ else if (response == Response . ERROR )
136+ statsMap. get(UNRESTORED_VERSIONS ). add(" ${ loggingName} - module: ${ restoreVersion} " )
137+ else
138+ statsMap. put(NUM_RESTORED , statsMap. get(NUM_RESTORED )+1 )
63139
140+ response = makeRestoreRequest(moduleName, restoreVersion, " api" )
141+ if (response == Response . NOT_FOUND )
142+ statsMap. put(NUM_NOT_FOUND , statsMap. get(NUM_NOT_FOUND )+1 )
143+ else if (response == Response . ERROR )
144+ statsMap. get(UNRESTORED_VERSIONS ). add(" ${ loggingName} - api: ${ restoreVersion} " )
145+ else
146+ statsMap. put(NUM_RESTORED , statsMap. get(NUM_RESTORED )+1 )
64147 }
65148
66149 /**
67150 * This uses the Artifactory REST Api to request a restoration of a particular "item" (https://jfrog.com/help/r/jfrog-rest-apis/restore-item-from-trash-can)
68151 *
69- * @param artifactName the artifact whose version is to be deleted
70- * @param version the version of the artifact to delete (e.g., 21.11-SNAPSHOT)
152+ * @param artifactName the artifact whose version is to be restored
153+ * @param version the version of the artifact to restore (e.g., 21.11-SNAPSHOT)
71154 * @param type either "api" or "module"
72155 * @return Response summarizing http status from request
73156 * @throws GradleException if the restoration request throws an exception
@@ -76,7 +159,7 @@ class RestoreFromTrash extends DefaultTask
76159 {
77160 if (project. hasProperty(" dryRun" )) {
78161 logger. quiet(" \t Restoring version ${ version} of ${ artifactName} ${ type} -- Skipped for dry run" )
79- return
162+ return null
80163 }
81164
82165 CloseableHttpClient httpClient = HttpClients . createDefault()
0 commit comments