com.elestrago.unity.package-tools 2.5.2 → 2.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CAHNGELOG.md +21 -0
- package/Documentation~/api.md +156 -66
- package/Documentation~/examples/ciutils-exportlegacypackage.md +32 -0
- package/Documentation~/examples/ciutils-exportpackagesource.md +38 -0
- package/Documentation~/examples/ciutils-generate.md +13 -8
- package/Documentation~/examples/ciutils-listconfigs.md +36 -0
- package/Documentation~/examples/packagetoolapi-exportlegacypackage.md +39 -0
- package/Documentation~/examples/packagetoolapi-exportpackagesource.md +40 -0
- package/Documentation~/examples/packagetoolapi-findconfig.md +46 -0
- package/Documentation~/examples/packagetoolapi-generateversionconstants.md +42 -0
- package/Documentation~/examples/packagetoolapi-getconfig.md +37 -0
- package/Documentation~/examples/packagetoolapi-getconfigs.md +36 -0
- package/Documentation~/examples/preparedll.md +1 -1
- package/Documentation~/examples.md +12 -1
- package/Documentation~/manual.md +39 -23
- package/Editor/CIUtils.cs +273 -74
- package/Editor/EditorConstants.cs +21 -1
- package/Editor/Inspectors/PackageManifestConfigInspector.cs +16 -3
- package/Editor/PackageToolApi.cs +141 -0
- package/Editor/PackageToolApi.cs.meta +11 -0
- package/Editor/Tools/CIResultModel.cs +107 -0
- package/Editor/Tools/CIResultModel.cs.meta +11 -0
- package/Editor/Tools/CodeGenTools.cs +8 -2
- package/Editor/Tools/FileTools.cs +76 -46
- package/Editor/Tools/UnityFileTools.cs +16 -2
- package/README.md +17 -8
- package/Samples~/ClaudeSkills/unity-package-docs/SKILL.md +6 -1
- package/package.json +4 -4
package/Editor/CIUtils.cs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
2
3
|
using System.IO;
|
|
3
4
|
using System.Linq;
|
|
4
5
|
using System.Text;
|
|
@@ -9,7 +10,8 @@ using UnityEngine;
|
|
|
9
10
|
namespace PackageTool
|
|
10
11
|
{
|
|
11
12
|
/// <summary>
|
|
12
|
-
/// Continuous-integration API for package tools.
|
|
13
|
+
/// Continuous-integration API for package tools. Every entry point here is meant to be invoked through
|
|
14
|
+
/// Unity's -executeMethod and reads its arguments as key=value command-line pairs.
|
|
13
15
|
/// </summary>
|
|
14
16
|
public static class CIUtils
|
|
15
17
|
{
|
|
@@ -18,6 +20,8 @@ namespace PackageTool
|
|
|
18
20
|
private const string VERSION_ARG_KEY = "version";
|
|
19
21
|
private const string PREVIEW_ARG_KEY = "preview";
|
|
20
22
|
private const string GENERATE_VERSION_CONSTANTS_ARG_KEY = "generateversionconstants";
|
|
23
|
+
private const string RESULT_PATH_ARG_KEY = "resultpath";
|
|
24
|
+
private const string EXIT_ON_FINISH_ARG_KEY = "exitonfinish";
|
|
21
25
|
|
|
22
26
|
// Logs
|
|
23
27
|
private const string LOG_PREFIX = "[Package Tools] ";
|
|
@@ -49,6 +53,10 @@ namespace PackageTool
|
|
|
49
53
|
private const string CI_SKIPPING_PACKAGE_SOURCE_FORMAT = LOG_PREFIX +
|
|
50
54
|
"Skipping Package Source for Config [{0}] with ID: [{1}] as no output path is present in config.";
|
|
51
55
|
|
|
56
|
+
private const string CI_LISTING_CONFIGS = LOG_PREFIX + "Listing [{0}] configs in project.";
|
|
57
|
+
private const string CI_EXPORT_FAILED_FORMAT = LOG_PREFIX + "Export failed for [{0}]:\n\n{1}";
|
|
58
|
+
private const string CI_UNEXPECTED_ERROR_FORMAT = "An unexpected error occured during package generation:\n\n{0}";
|
|
59
|
+
|
|
52
60
|
private static readonly StringBuilder StringBuilder;
|
|
53
61
|
|
|
54
62
|
private static bool IsRunningOnCI => !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("CI"));
|
|
@@ -66,123 +74,232 @@ namespace PackageTool
|
|
|
66
74
|
{
|
|
67
75
|
Debug.Log(CI_STARTING);
|
|
68
76
|
|
|
69
|
-
|
|
77
|
+
PrepareDllInternal();
|
|
78
|
+
|
|
79
|
+
var commandLineArgs = GetLoggedCommandLineArguments();
|
|
80
|
+
var results = new List<CIResultModel>();
|
|
81
|
+
var hasError = false;
|
|
70
82
|
|
|
71
83
|
try
|
|
72
84
|
{
|
|
73
85
|
EditorApplication.LockReloadAssemblies();
|
|
74
86
|
AssetDatabase.StartAssetEditing();
|
|
75
87
|
|
|
76
|
-
// Get command line args and log them
|
|
77
|
-
var commandLineArgs = CommandLineTools.GetKVPCommandLineArguments();
|
|
78
|
-
|
|
79
|
-
StringBuilder.Clear();
|
|
80
|
-
const string cliArgFormat = "{0} => {1}";
|
|
81
|
-
foreach (var commandLineArg in commandLineArgs)
|
|
82
|
-
{
|
|
83
|
-
StringBuilder.AppendFormat(cliArgFormat, commandLineArg.Key, commandLineArg.Value);
|
|
84
|
-
StringBuilder.AppendLine();
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
Debug.LogFormat(CI_COMMAND_LINE_ARGS_PARSED_FORMAT, StringBuilder);
|
|
88
|
-
|
|
89
88
|
// Attempt to parse CLI-passed version, if present.
|
|
90
|
-
|
|
91
|
-
if (commandLineArgs.TryGetValue(VERSION_ARG_KEY, out var versionRawValue))
|
|
92
|
-
version = (string)versionRawValue;
|
|
89
|
+
var version = GetStringArgument(commandLineArgs, VERSION_ARG_KEY);
|
|
93
90
|
|
|
94
|
-
// Attempt to parse CLI-passed
|
|
91
|
+
// Attempt to parse CLI-passed preview flag, if present.
|
|
95
92
|
bool? isPreview = null;
|
|
96
93
|
if (commandLineArgs.TryGetValue(PREVIEW_ARG_KEY, out var previewRawValue))
|
|
97
94
|
isPreview = bool.Parse((string)previewRawValue);
|
|
98
95
|
|
|
99
96
|
// See if we should generate version constants
|
|
100
|
-
var generateVersionConstants =
|
|
101
|
-
if (commandLineArgs.TryGetValue(
|
|
102
|
-
GENERATE_VERSION_CONSTANTS_ARG_KEY,
|
|
103
|
-
out var generateVersionConstantsRawValue))
|
|
104
|
-
generateVersionConstants = bool.Parse(generateVersionConstantsRawValue.ToString());
|
|
97
|
+
var generateVersionConstants = GetBoolArgument(commandLineArgs, GENERATE_VERSION_CONSTANTS_ARG_KEY);
|
|
105
98
|
|
|
106
99
|
// Get all package manifests in project
|
|
107
|
-
var allPackageManifestConfigs =
|
|
100
|
+
var allPackageManifestConfigs = PackageToolApi.GetConfigs();
|
|
108
101
|
|
|
109
102
|
Debug.LogFormat(CI_FOUND_CONFIGS, allPackageManifestConfigs.Length);
|
|
110
103
|
|
|
111
104
|
// Check to see if any IDs have been passed for specific configs
|
|
112
|
-
|
|
113
|
-
if (commandLineArgs.TryGetValue(ID_ARG_KEY, out var arg))
|
|
114
|
-
{
|
|
115
|
-
Debug.Log(CI_USING_ONLY_CONFIGS_FROM_ARG);
|
|
116
|
-
|
|
117
|
-
const char commaChar = ',';
|
|
118
|
-
var idArgValue = arg.ToString();
|
|
119
|
-
configIds = idArgValue.Split(commaChar);
|
|
120
|
-
}
|
|
121
|
-
// Otherwise generate all package manifest configs in project.
|
|
122
|
-
else
|
|
123
|
-
{
|
|
124
|
-
Debug.Log(CI_USING_ALL_CONFIGS);
|
|
105
|
+
var selectors = GetSelectors(commandLineArgs, allPackageManifestConfigs);
|
|
125
106
|
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// For each matching config ID, find the matching package manifest config and generate any relevant packages.
|
|
107
|
+
// For each matching selector, find the matching package manifest config and generate any relevant packages.
|
|
130
108
|
Debug.Log(CI_GENERATION_STARTING);
|
|
131
|
-
foreach (var
|
|
109
|
+
foreach (var selector in selectors)
|
|
132
110
|
{
|
|
133
|
-
var matchingConfig =
|
|
134
|
-
string.Compare(x.Id, configId, StringComparison.OrdinalIgnoreCase) == 0);
|
|
111
|
+
var matchingConfig = PackageToolApi.FindConfig(selector, allPackageManifestConfigs);
|
|
135
112
|
|
|
136
|
-
// If a config cannot be found matching
|
|
113
|
+
// If a config cannot be found matching the selector, skip it and continue.
|
|
137
114
|
if (matchingConfig == null)
|
|
138
115
|
{
|
|
139
|
-
Debug.LogWarningFormat(CI_PACKAGE_NOT_FOUND_FORMAT,
|
|
116
|
+
Debug.LogWarningFormat(CI_PACKAGE_NOT_FOUND_FORMAT, selector);
|
|
117
|
+
results.Add(CIResultModel.CreateFailure(
|
|
118
|
+
selector,
|
|
119
|
+
string.Format(EditorConstants.CONFIG_NOT_FOUND_ERROR_FORMAT, selector)));
|
|
140
120
|
|
|
141
121
|
continue;
|
|
142
122
|
}
|
|
143
123
|
|
|
144
124
|
var configName = matchingConfig.name;
|
|
125
|
+
var configId = matchingConfig.Id;
|
|
126
|
+
var result = CIResultModel.CreateForConfig(selector, matchingConfig);
|
|
127
|
+
results.Add(result);
|
|
145
128
|
|
|
146
129
|
Debug.LogFormat(CI_PACKAGE_FOUND_FORMAT, configName, configId);
|
|
147
130
|
|
|
148
|
-
|
|
149
|
-
if (!string.IsNullOrEmpty(version))
|
|
131
|
+
try
|
|
150
132
|
{
|
|
151
|
-
|
|
152
|
-
|
|
133
|
+
// If set to generate version constants, do so.
|
|
134
|
+
if (generateVersionConstants)
|
|
135
|
+
result.VersionConstantsPath = PackageToolApi.GenerateVersionConstants(matchingConfig);
|
|
136
|
+
|
|
137
|
+
// Otherwise generate the corresponding legacy unity package and package source if their
|
|
138
|
+
// output paths have been defined
|
|
139
|
+
if (!string.IsNullOrEmpty(matchingConfig.legacyPackageDestinationPath))
|
|
140
|
+
{
|
|
141
|
+
Debug.LogFormat(CI_GENERATING_LEGACY_PACKAGE_FORMAT, configName, configId);
|
|
142
|
+
|
|
143
|
+
result.LegacyPackagePath = PackageToolApi.ExportLegacyPackage(matchingConfig, version);
|
|
144
|
+
}
|
|
145
|
+
else
|
|
146
|
+
{
|
|
147
|
+
Debug.LogFormat(CI_SKIPPING_LEGACY_PACKAGE_FORMAT, configName, configId);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (!string.IsNullOrEmpty(matchingConfig.packageDestinationPath))
|
|
151
|
+
{
|
|
152
|
+
Debug.LogFormat(CI_GENERATING_PACKAGE_SOURCE_FORMAT, configName, configId);
|
|
153
|
+
|
|
154
|
+
result.PackageSourcePath = PackageToolApi.ExportPackageSource(matchingConfig, version);
|
|
155
|
+
}
|
|
156
|
+
else
|
|
157
|
+
{
|
|
158
|
+
Debug.LogFormat(CI_SKIPPING_PACKAGE_SOURCE_FORMAT, configName, configId);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
result.PackageVersion = matchingConfig.packageVersion;
|
|
153
162
|
}
|
|
163
|
+
catch (Exception e)
|
|
164
|
+
{
|
|
165
|
+
result.Success = false;
|
|
166
|
+
result.Error = e.Message;
|
|
167
|
+
hasError = true;
|
|
168
|
+
|
|
169
|
+
Debug.LogErrorFormat(CI_EXPORT_FAILED_FORMAT, configName, e);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch (Exception e)
|
|
174
|
+
{
|
|
175
|
+
results.Add(CIResultModel.CreateFailure(null, e.Message));
|
|
176
|
+
hasError = true;
|
|
177
|
+
|
|
178
|
+
Debug.LogErrorFormat(CI_UNEXPECTED_ERROR_FORMAT, e);
|
|
179
|
+
}
|
|
180
|
+
finally
|
|
181
|
+
{
|
|
182
|
+
AssetDatabase.StopAssetEditing();
|
|
183
|
+
EditorApplication.UnlockReloadAssemblies();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
Debug.Log(CI_COMPLETE);
|
|
187
|
+
|
|
188
|
+
// Generate has always logged and continued on a missing config, so it only fails on a real error.
|
|
189
|
+
Finish(commandLineArgs, results, !hasError);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/// <summary>
|
|
193
|
+
/// Writes every <see cref="PackageManifestConfig"/> in the project to the file passed in the
|
|
194
|
+
/// 'resultpath' argument so that callers can discover which selectors are valid.
|
|
195
|
+
/// </summary>
|
|
196
|
+
public static void ListConfigs()
|
|
197
|
+
{
|
|
198
|
+
var commandLineArgs = GetLoggedCommandLineArguments();
|
|
199
|
+
var configs = PackageToolApi.GetConfigs();
|
|
200
|
+
|
|
201
|
+
Debug.LogFormat(CI_LISTING_CONFIGS, configs.Length);
|
|
154
202
|
|
|
155
|
-
|
|
156
|
-
if (generateVersionConstants) CodeGenTools.GenerateVersionConstants(matchingConfig);
|
|
203
|
+
var models = configs.Select(CIConfigModel.CreateFromConfig).ToList();
|
|
157
204
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
205
|
+
CIResultTools.WriteResultFile(GetStringArgument(commandLineArgs, RESULT_PATH_ARG_KEY), models);
|
|
206
|
+
|
|
207
|
+
ExitIfRequested(commandLineArgs, true);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/// <summary>
|
|
211
|
+
/// Exports the package source of every selected <see cref="PackageManifestConfig"/>.
|
|
212
|
+
/// </summary>
|
|
213
|
+
public static void ExportPackageSource() => RunExport(exportSource: true, exportLegacy: false);
|
|
214
|
+
|
|
215
|
+
/// <summary>
|
|
216
|
+
/// Exports every selected <see cref="PackageManifestConfig"/> as a legacy unity package.
|
|
217
|
+
/// </summary>
|
|
218
|
+
public static void ExportLegacyPackage() => RunExport(exportSource: false, exportLegacy: true);
|
|
219
|
+
|
|
220
|
+
private static void RunExport(bool exportSource, bool exportLegacy)
|
|
221
|
+
{
|
|
222
|
+
var commandLineArgs = GetLoggedCommandLineArguments();
|
|
223
|
+
var results = new List<CIResultModel>();
|
|
224
|
+
|
|
225
|
+
try
|
|
226
|
+
{
|
|
227
|
+
EditorApplication.LockReloadAssemblies();
|
|
228
|
+
AssetDatabase.StartAssetEditing();
|
|
229
|
+
|
|
230
|
+
var version = GetStringArgument(commandLineArgs, VERSION_ARG_KEY);
|
|
231
|
+
var generateVersionConstants = GetBoolArgument(commandLineArgs, GENERATE_VERSION_CONSTANTS_ARG_KEY);
|
|
232
|
+
var allConfigs = PackageToolApi.GetConfigs();
|
|
233
|
+
|
|
234
|
+
Debug.LogFormat(CI_FOUND_CONFIGS, allConfigs.Length);
|
|
235
|
+
|
|
236
|
+
foreach (var selector in GetSelectors(commandLineArgs, allConfigs))
|
|
237
|
+
{
|
|
238
|
+
PackageManifestConfig config;
|
|
239
|
+
try
|
|
240
|
+
{
|
|
241
|
+
config = PackageToolApi.FindConfig(selector, allConfigs);
|
|
242
|
+
}
|
|
243
|
+
catch (Exception e)
|
|
161
244
|
{
|
|
162
|
-
|
|
245
|
+
results.Add(CIResultModel.CreateFailure(selector, e.Message));
|
|
163
246
|
|
|
164
|
-
|
|
247
|
+
Debug.LogErrorFormat(CI_EXPORT_FAILED_FORMAT, selector, e);
|
|
248
|
+
|
|
249
|
+
continue;
|
|
165
250
|
}
|
|
166
|
-
|
|
251
|
+
|
|
252
|
+
// Unlike Generate, asking for a package that is not there is a failure and not a skip.
|
|
253
|
+
if (config == null)
|
|
167
254
|
{
|
|
168
|
-
|
|
255
|
+
var error = string.Format(EditorConstants.CONFIG_NOT_FOUND_ERROR_FORMAT, selector);
|
|
256
|
+
results.Add(CIResultModel.CreateFailure(selector, error));
|
|
257
|
+
|
|
258
|
+
Debug.LogError(error);
|
|
259
|
+
|
|
260
|
+
continue;
|
|
169
261
|
}
|
|
170
262
|
|
|
171
|
-
|
|
263
|
+
var result = CIResultModel.CreateForConfig(selector, config);
|
|
264
|
+
results.Add(result);
|
|
265
|
+
|
|
266
|
+
Debug.LogFormat(CI_PACKAGE_FOUND_FORMAT, config.name, config.Id);
|
|
267
|
+
|
|
268
|
+
try
|
|
172
269
|
{
|
|
173
|
-
|
|
270
|
+
if (generateVersionConstants)
|
|
271
|
+
result.VersionConstantsPath = PackageToolApi.GenerateVersionConstants(config);
|
|
272
|
+
|
|
273
|
+
if (exportLegacy)
|
|
274
|
+
{
|
|
275
|
+
Debug.LogFormat(CI_GENERATING_LEGACY_PACKAGE_FORMAT, config.name, config.Id);
|
|
276
|
+
|
|
277
|
+
result.LegacyPackagePath = PackageToolApi.ExportLegacyPackage(config, version);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (exportSource)
|
|
281
|
+
{
|
|
282
|
+
Debug.LogFormat(CI_GENERATING_PACKAGE_SOURCE_FORMAT, config.name, config.Id);
|
|
174
283
|
|
|
175
|
-
|
|
284
|
+
result.PackageSourcePath = PackageToolApi.ExportPackageSource(config, version);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
result.PackageVersion = config.packageVersion;
|
|
176
288
|
}
|
|
177
|
-
|
|
289
|
+
catch (Exception e)
|
|
178
290
|
{
|
|
179
|
-
|
|
291
|
+
result.Success = false;
|
|
292
|
+
result.Error = e.Message;
|
|
293
|
+
|
|
294
|
+
Debug.LogErrorFormat(CI_EXPORT_FAILED_FORMAT, config.name, e);
|
|
180
295
|
}
|
|
181
296
|
}
|
|
182
297
|
}
|
|
183
298
|
catch (Exception e)
|
|
184
299
|
{
|
|
185
|
-
|
|
300
|
+
results.Add(CIResultModel.CreateFailure(null, e.Message));
|
|
301
|
+
|
|
302
|
+
Debug.LogErrorFormat(CI_UNEXPECTED_ERROR_FORMAT, e);
|
|
186
303
|
}
|
|
187
304
|
finally
|
|
188
305
|
{
|
|
@@ -190,17 +307,30 @@ namespace PackageTool
|
|
|
190
307
|
EditorApplication.UnlockReloadAssemblies();
|
|
191
308
|
}
|
|
192
309
|
|
|
193
|
-
|
|
310
|
+
Finish(commandLineArgs, results, results.Count > 0 && results.All(x => x.Success));
|
|
194
311
|
}
|
|
195
312
|
|
|
313
|
+
/// <summary>
|
|
314
|
+
/// Sets the platform compatibility of every plugin in the source path of the project's
|
|
315
|
+
/// <see cref="PackageManifestConfig"/> so that editor assemblies are not shipped as runtime ones.
|
|
316
|
+
/// This is a command-line entry point in its own right, so it exits the editor when running on CI.
|
|
317
|
+
/// </summary>
|
|
196
318
|
[MenuItem("Tools/PackageTools/PrepareDll")]
|
|
197
319
|
public static void PrepareDll()
|
|
320
|
+
{
|
|
321
|
+
var success = PrepareDllInternal();
|
|
322
|
+
|
|
323
|
+
if (IsRunningOnCI)
|
|
324
|
+
EditorApplication.Exit(success ? 0 : 1);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
private static bool PrepareDllInternal()
|
|
198
328
|
{
|
|
199
329
|
try
|
|
200
330
|
{
|
|
201
331
|
Debug.Log($"[{nameof(CIUtils)}] PrepareDll");
|
|
202
332
|
|
|
203
|
-
var packageManifestConfig =
|
|
333
|
+
var packageManifestConfig = PackageToolApi.GetConfigs().Single();
|
|
204
334
|
var sourcePath = packageManifestConfig.sourcePath;
|
|
205
335
|
|
|
206
336
|
Debug.Log($"[{nameof(CIUtils)}] Find assets in path: {sourcePath}");
|
|
@@ -231,17 +361,86 @@ namespace PackageTool
|
|
|
231
361
|
}
|
|
232
362
|
|
|
233
363
|
Debug.Log($"[{nameof(CIUtils)}] Complete dll import");
|
|
364
|
+
|
|
365
|
+
return true;
|
|
234
366
|
}
|
|
235
367
|
catch (Exception e)
|
|
236
368
|
{
|
|
237
369
|
Debug.LogException(e);
|
|
238
370
|
|
|
239
|
-
|
|
240
|
-
EditorApplication.Exit(1);
|
|
371
|
+
return false;
|
|
241
372
|
}
|
|
373
|
+
}
|
|
242
374
|
|
|
243
|
-
|
|
244
|
-
|
|
375
|
+
private static Dictionary<string, object> GetLoggedCommandLineArguments()
|
|
376
|
+
{
|
|
377
|
+
var commandLineArgs = CommandLineTools.GetKVPCommandLineArguments();
|
|
378
|
+
|
|
379
|
+
StringBuilder.Clear();
|
|
380
|
+
const string cliArgFormat = "{0} => {1}";
|
|
381
|
+
foreach (var commandLineArg in commandLineArgs)
|
|
382
|
+
{
|
|
383
|
+
StringBuilder.AppendFormat(cliArgFormat, commandLineArg.Key, commandLineArg.Value);
|
|
384
|
+
StringBuilder.AppendLine();
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
Debug.LogFormat(CI_COMMAND_LINE_ARGS_PARSED_FORMAT, StringBuilder);
|
|
388
|
+
|
|
389
|
+
return commandLineArgs;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/// <summary>
|
|
393
|
+
/// Returns the selectors passed in the 'id' argument, or a selector for every config in the project
|
|
394
|
+
/// when the argument is absent. A selector is a config id, a package name or a config asset name.
|
|
395
|
+
/// </summary>
|
|
396
|
+
private static string[] GetSelectors(
|
|
397
|
+
Dictionary<string, object> commandLineArgs,
|
|
398
|
+
PackageManifestConfig[] allConfigs)
|
|
399
|
+
{
|
|
400
|
+
if (commandLineArgs.TryGetValue(ID_ARG_KEY, out var arg) && arg != null)
|
|
401
|
+
{
|
|
402
|
+
Debug.Log(CI_USING_ONLY_CONFIGS_FROM_ARG);
|
|
403
|
+
|
|
404
|
+
const char commaChar = ',';
|
|
405
|
+
|
|
406
|
+
return arg.ToString()
|
|
407
|
+
.Split(commaChar)
|
|
408
|
+
.Select(x => x.Trim())
|
|
409
|
+
.Where(x => !string.IsNullOrEmpty(x))
|
|
410
|
+
.ToArray();
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
Debug.Log(CI_USING_ALL_CONFIGS);
|
|
414
|
+
|
|
415
|
+
return allConfigs.Select(x => x.Id).ToArray();
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
private static string GetStringArgument(Dictionary<string, object> commandLineArgs, string key)
|
|
419
|
+
{
|
|
420
|
+
return commandLineArgs.TryGetValue(key, out var rawValue) ? (string)rawValue : null;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
private static bool GetBoolArgument(Dictionary<string, object> commandLineArgs, string key)
|
|
424
|
+
{
|
|
425
|
+
return commandLineArgs.TryGetValue(key, out var rawValue) && bool.Parse(rawValue.ToString());
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
private static void Finish(
|
|
429
|
+
Dictionary<string, object> commandLineArgs,
|
|
430
|
+
IReadOnlyList<CIResultModel> results,
|
|
431
|
+
bool success)
|
|
432
|
+
{
|
|
433
|
+
// The result file is always written before a potential exit so callers never race the editor.
|
|
434
|
+
CIResultTools.WriteResultFile(GetStringArgument(commandLineArgs, RESULT_PATH_ARG_KEY), results);
|
|
435
|
+
|
|
436
|
+
ExitIfRequested(commandLineArgs, success);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
private static void ExitIfRequested(Dictionary<string, object> commandLineArgs, bool success)
|
|
440
|
+
{
|
|
441
|
+
var exitOnFinish = IsRunningOnCI || GetBoolArgument(commandLineArgs, EXIT_ON_FINISH_ARG_KEY);
|
|
442
|
+
if (exitOnFinish)
|
|
443
|
+
EditorApplication.Exit(success ? 0 : 1);
|
|
245
444
|
}
|
|
246
445
|
}
|
|
247
|
-
}
|
|
446
|
+
}
|
|
@@ -41,7 +41,6 @@ namespace PackageTool
|
|
|
41
41
|
public const string ASSET_EXTENSION = ".asset";
|
|
42
42
|
public const string META_EXTENSION = ".meta";
|
|
43
43
|
public const string META_FORMAT = "{0}" + META_EXTENSION;
|
|
44
|
-
public const string GENERATED_FOLDER_NAME = "Generated";
|
|
45
44
|
public const string UNITY_PACKAGE_NAME_FORMAT = "{0}_v{1}.unityPackage";
|
|
46
45
|
public const char EMPTY_SPACE = ' ';
|
|
47
46
|
public const char UNDERSCORE = '_';
|
|
@@ -105,6 +104,27 @@ namespace PackageTool
|
|
|
105
104
|
public const string PACKAGE_UPDATE_SUCCESS_FORMAT =
|
|
106
105
|
"[Package Tools] Successfully updated package source for [{0}].";
|
|
107
106
|
|
|
107
|
+
public const string PACKAGE_JSON_META_MISSING_FORMAT =
|
|
108
|
+
"[Package Tools] No meta file was created for [{0}]; it will be missing from the exported package. " +
|
|
109
|
+
"Run the export again once Unity has finished importing.";
|
|
110
|
+
|
|
111
|
+
public const string NO_SOURCE_PATH_ERROR_FORMAT =
|
|
112
|
+
"[Package Tools] Config [{0}] has no source path set.";
|
|
113
|
+
|
|
114
|
+
public const string NO_PACKAGE_DESTINATION_PATH_ERROR_FORMAT =
|
|
115
|
+
"[Package Tools] Config [{0}] has no package destination path set.";
|
|
116
|
+
|
|
117
|
+
public const string NO_LEGACY_DESTINATION_PATH_ERROR_FORMAT =
|
|
118
|
+
"[Package Tools] Config [{0}] has no legacy package destination path set.";
|
|
119
|
+
|
|
120
|
+
public const string CONFIG_NOT_FOUND_ERROR_FORMAT =
|
|
121
|
+
"[Package Tools] No PackageManifestConfig matches [{0}]. Selectors match the config id, the package " +
|
|
122
|
+
"name or the asset name.";
|
|
123
|
+
|
|
124
|
+
public const string AMBIGUOUS_CONFIG_ERROR_FORMAT =
|
|
125
|
+
"[Package Tools] Selector [{0}] matches more than one PackageManifestConfig: {1}. Use the config id " +
|
|
126
|
+
"instead.";
|
|
127
|
+
|
|
108
128
|
public const string AGENT_LOCKED_FILE_MARKER_FORMAT =
|
|
109
129
|
"<!--\n" +
|
|
110
130
|
"AGENT NOTE: This file is auto-generated and locked for direct edits.\n" +
|
|
@@ -22,6 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
22
22
|
SOFTWARE.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
+
using System;
|
|
25
26
|
using PackageTool.Tools;
|
|
26
27
|
using UnityEditor;
|
|
27
28
|
using UnityEditorInternal;
|
|
@@ -279,17 +280,29 @@ namespace PackageTool.Inspectors
|
|
|
279
280
|
EditorConstants.GENERATE_VERSION_CONSTANTS_BUTTON_TEXT,
|
|
280
281
|
EditorConstants.GENERATE_VERSION_CONSTANTS_TOOLTIP)))
|
|
281
282
|
{
|
|
282
|
-
|
|
283
|
+
RunAction(config, PackageToolApi.GenerateVersionConstants);
|
|
283
284
|
}
|
|
284
285
|
|
|
285
286
|
if (GUILayout.Button(EditorConstants.UPDATE_PACKAGE_BUTTON_TEXT))
|
|
286
287
|
{
|
|
287
|
-
|
|
288
|
+
RunAction(config, x => PackageToolApi.ExportPackageSource(x));
|
|
288
289
|
}
|
|
289
290
|
|
|
290
291
|
if (GUILayout.Button(EditorConstants.EXPORT_LEGACY_PACKAGE_BUTTON_TEXT))
|
|
291
292
|
{
|
|
292
|
-
|
|
293
|
+
RunAction(config, x => PackageToolApi.ExportLegacyPackage(x));
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
private static void RunAction(PackageManifestConfig config, Func<PackageManifestConfig, string> action)
|
|
298
|
+
{
|
|
299
|
+
try
|
|
300
|
+
{
|
|
301
|
+
action.Invoke(config);
|
|
302
|
+
}
|
|
303
|
+
catch (Exception e)
|
|
304
|
+
{
|
|
305
|
+
Debug.LogException(e, config);
|
|
293
306
|
}
|
|
294
307
|
}
|
|
295
308
|
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using System.Linq;
|
|
4
|
+
using PackageTool.Tools;
|
|
5
|
+
using UnityEditor;
|
|
6
|
+
|
|
7
|
+
namespace PackageTool
|
|
8
|
+
{
|
|
9
|
+
/// <summary>
|
|
10
|
+
/// Public entry points for driving the package tools from other editor code. Every method throws on
|
|
11
|
+
/// failure and returns the path of what it produced.
|
|
12
|
+
/// </summary>
|
|
13
|
+
public static class PackageToolApi
|
|
14
|
+
{
|
|
15
|
+
/// <summary>
|
|
16
|
+
/// Returns all <see cref="PackageManifestConfig"/> assets in the project.
|
|
17
|
+
/// </summary>
|
|
18
|
+
public static PackageManifestConfig[] GetConfigs() => PackageManifestTools.GetAllConfigs();
|
|
19
|
+
|
|
20
|
+
/// <summary>
|
|
21
|
+
/// Returns the <see cref="PackageManifestConfig"/> matching <paramref name="selector"/>, which is
|
|
22
|
+
/// compared case-insensitively against the config id, the package name and the asset name, in that
|
|
23
|
+
/// order. Returns null when nothing matches and throws when the selector is ambiguous.
|
|
24
|
+
/// </summary>
|
|
25
|
+
/// <param name="selector"></param>
|
|
26
|
+
public static PackageManifestConfig FindConfig(string selector) => FindConfig(selector, GetConfigs());
|
|
27
|
+
|
|
28
|
+
/// <summary>
|
|
29
|
+
/// Returns the <see cref="PackageManifestConfig"/> matching <paramref name="selector"/> from
|
|
30
|
+
/// <paramref name="configs"/>. Use this overload to resolve several selectors against a single lookup
|
|
31
|
+
/// of the project.
|
|
32
|
+
/// </summary>
|
|
33
|
+
/// <param name="selector"></param>
|
|
34
|
+
/// <param name="configs"></param>
|
|
35
|
+
public static PackageManifestConfig FindConfig(string selector, PackageManifestConfig[] configs)
|
|
36
|
+
{
|
|
37
|
+
if (string.IsNullOrEmpty(selector))
|
|
38
|
+
throw new ArgumentNullException(nameof(selector));
|
|
39
|
+
if (configs == null)
|
|
40
|
+
throw new ArgumentNullException(nameof(configs));
|
|
41
|
+
|
|
42
|
+
var matches = MatchByField(configs, selector, config => config.Id);
|
|
43
|
+
if (matches.Count == 0)
|
|
44
|
+
matches = MatchByField(configs, selector, config => config.packageName);
|
|
45
|
+
if (matches.Count == 0)
|
|
46
|
+
matches = MatchByField(configs, selector, config => config.name);
|
|
47
|
+
|
|
48
|
+
if (matches.Count > 1)
|
|
49
|
+
{
|
|
50
|
+
var candidates = string.Join(", ", matches.Select(x => $"{x.name} ({x.Id})"));
|
|
51
|
+
throw new InvalidOperationException(
|
|
52
|
+
string.Format(EditorConstants.AMBIGUOUS_CONFIG_ERROR_FORMAT, selector, candidates));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return matches.Count == 1 ? matches[0] : null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// <summary>
|
|
59
|
+
/// Returns the <see cref="PackageManifestConfig"/> matching <paramref name="selector"/> and throws
|
|
60
|
+
/// when no config matches it.
|
|
61
|
+
/// </summary>
|
|
62
|
+
/// <param name="selector"></param>
|
|
63
|
+
public static PackageManifestConfig GetConfig(string selector)
|
|
64
|
+
{
|
|
65
|
+
var config = FindConfig(selector);
|
|
66
|
+
if (config == null)
|
|
67
|
+
throw new InvalidOperationException(
|
|
68
|
+
string.Format(EditorConstants.CONFIG_NOT_FOUND_ERROR_FORMAT, selector));
|
|
69
|
+
|
|
70
|
+
return config;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/// <summary>
|
|
74
|
+
/// Generates the VersionConstants.cs file for <paramref name="config"/> and returns its path, or null
|
|
75
|
+
/// when the config has no version constants path set.
|
|
76
|
+
/// </summary>
|
|
77
|
+
/// <param name="config"></param>
|
|
78
|
+
public static string GenerateVersionConstants(PackageManifestConfig config)
|
|
79
|
+
{
|
|
80
|
+
if (config == null)
|
|
81
|
+
throw new ArgumentNullException(nameof(config));
|
|
82
|
+
|
|
83
|
+
return CodeGenTools.GenerateVersionConstants(config);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/// <summary>
|
|
87
|
+
/// Exports the package source of <paramref name="config"/> to its
|
|
88
|
+
/// <see cref="PackageManifestConfig.packageDestinationPath"/> and returns the path of the written
|
|
89
|
+
/// package.json. When <paramref name="version"/> is set it replaces the version on the config asset
|
|
90
|
+
/// before the export.
|
|
91
|
+
/// </summary>
|
|
92
|
+
/// <param name="config"></param>
|
|
93
|
+
/// <param name="version"></param>
|
|
94
|
+
public static string ExportPackageSource(PackageManifestConfig config, string version = null)
|
|
95
|
+
{
|
|
96
|
+
if (config == null)
|
|
97
|
+
throw new ArgumentNullException(nameof(config));
|
|
98
|
+
|
|
99
|
+
ApplyVersion(config, version);
|
|
100
|
+
|
|
101
|
+
return FileTools.CreateOrUpdatePackageSourceOrThrow(config);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/// <summary>
|
|
105
|
+
/// Exports <paramref name="config"/> as a legacy unity package to its
|
|
106
|
+
/// <see cref="PackageManifestConfig.legacyPackageDestinationPath"/> and returns the path of the
|
|
107
|
+
/// written file. When <paramref name="version"/> is set it replaces the version on the config asset
|
|
108
|
+
/// before the export.
|
|
109
|
+
/// </summary>
|
|
110
|
+
/// <param name="config"></param>
|
|
111
|
+
/// <param name="version"></param>
|
|
112
|
+
public static string ExportLegacyPackage(PackageManifestConfig config, string version = null)
|
|
113
|
+
{
|
|
114
|
+
if (config == null)
|
|
115
|
+
throw new ArgumentNullException(nameof(config));
|
|
116
|
+
|
|
117
|
+
ApplyVersion(config, version);
|
|
118
|
+
|
|
119
|
+
return UnityFileTools.CompileLegacyPackage(config);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
private static void ApplyVersion(PackageManifestConfig config, string version)
|
|
123
|
+
{
|
|
124
|
+
if (string.IsNullOrEmpty(version) || config.packageVersion == version)
|
|
125
|
+
return;
|
|
126
|
+
|
|
127
|
+
config.packageVersion = version;
|
|
128
|
+
EditorUtility.SetDirty(config);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private static List<PackageManifestConfig> MatchByField(
|
|
132
|
+
PackageManifestConfig[] configs,
|
|
133
|
+
string selector,
|
|
134
|
+
Func<PackageManifestConfig, string> getField)
|
|
135
|
+
{
|
|
136
|
+
return configs
|
|
137
|
+
.Where(x => string.Compare(getField(x), selector, StringComparison.OrdinalIgnoreCase) == 0)
|
|
138
|
+
.ToList();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|