/
Repack.cs
189 lines (159 loc) · 6.63 KB
/
Repack.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using Inedo.UPack.Packaging;
namespace Inedo.UPack.CLI
{
[DisplayName("repack")]
[Description("Creates a new universal package by repackaging an existing package with a new version number and audit information.")]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)]
internal sealed class Repack : Command
{
[Obsolete]
[AlternateName("manifest")]
[AlternateName("metadata")]
[ExtraArgument]
[ExpandPath]
public string Manifest { get; set; }
[DisplayName("source")]
[Description("The path of the existing upack file.")]
[PositionalArgument(0)]
[ExpandPath]
public string SourcePath { get; set; }
[DisplayName("targetDirectory")]
[Description("Directory where the .upack file will be created. If not specified, the current working directory is used.")]
[ExtraArgument]
[ExpandPath]
public string TargetDirectory { get; set; }
[Obsolete]
[AlternateName("group")]
[ExtraArgument]
public string Group { get; set; }
[Obsolete]
[AlternateName("name")]
[ExtraArgument]
public string Name { get; set; }
[DisplayName("newVersion")]
[AlternateName("version")]
[Description("New package version to use.")]
[ExtraArgument]
public string NewVersion { get; set; }
[Obsolete]
[AlternateName("title")]
[ExtraArgument]
public string Title { get; set; }
[Obsolete]
[AlternateName("description")]
[ExtraArgument]
public string PackageDescription { get; set; }
[Obsolete]
[AlternateName("icon")]
[ExtraArgument]
public string IconUrl { get; set; }
[Obsolete]
[AlternateName("no-audit")]
[ExtraArgument]
[DefaultValue(false)]
public bool NoAudit { get; set; }
[DisplayName("note")]
[Description("A description of the purpose for repackaging that will be entered as the audit note.")]
[ExtraArgument]
public string Note { get; set; }
[DisplayName("overwrite")]
[Description("Overwrite existing package file if it already exists.")]
[ExtraArgument]
[DefaultValue(false)]
public bool Overwrite { get; set; }
#pragma warning disable CS0612 // Type or member is obsolete
public override async Task<int> RunAsync(CancellationToken cancellationToken)
{
if (this.NoAudit && !string.IsNullOrEmpty(this.Note))
{
Console.Error.WriteLine("--no-audit cannot be used with --note.");
return 2;
}
var info = GetPackageMetadata(this.SourcePath);
var infoToMerge = GetMetadataToMerge();
var hash = GetSHA1(this.SourcePath);
var id = (string.IsNullOrEmpty(info.Group) ? "" : info.Group + "/") + info.Name + ":" + info.Version + ":" + hash;
foreach (var modifiedProperty in infoToMerge)
info[modifiedProperty.Key] = modifiedProperty.Value;
var error = ValidateManifest(info);
if (error != null)
{
Console.Error.WriteLine("Invalid {0}: {1}", string.IsNullOrWhiteSpace(this.Manifest) ? "parameters" : "upack.json", error);
return 2;
}
PrintManifest(info);
if (!this.NoAudit)
{
var entry = new RepackageHistoryEntry
{
Id = id,
Date = DateTimeOffset.Now,
Using = "upack/" + typeof(Repack).Assembly.GetName().Version.ToString(3),
By = Environment.UserName
};
if (!string.IsNullOrEmpty(this.Note))
entry.Reason = this.Note;
info.RepackageHistory.Add(entry);
}
string relativePackageFileName = $"{info.Name}-{info.Version:U}.upack";
string targetFileName = Path.Combine(this.TargetDirectory ?? Environment.CurrentDirectory, relativePackageFileName);
if (!this.Overwrite && File.Exists(targetFileName))
throw new UpackException($"Target file '{targetFileName}' exists and overwrite was set to false.");
string tmpPath = Path.GetTempFileName();
using (var existingPackage = new UniversalPackage(this.SourcePath))
using (var builder = new UniversalPackageBuilder(tmpPath, info))
{
var entries = from e in existingPackage.Entries
where !string.Equals(e.RawPath, "upack.json", StringComparison.OrdinalIgnoreCase)
select e;
foreach (var entry in entries)
{
cancellationToken.ThrowIfCancellationRequested();
if (entry.IsDirectory)
{
builder.AddEmptyDirectoryRaw(entry.RawPath);
}
else
{
using var stream = entry.Open();
await builder.AddFileRawAsync(stream, entry.RawPath, entry.Timestamp, cancellationToken);
}
}
}
Directory.CreateDirectory(Path.GetDirectoryName(targetFileName));
File.Delete(targetFileName);
File.Move(tmpPath, targetFileName);
return 0;
}
private UniversalPackageMetadata GetMetadataToMerge()
{
if (string.IsNullOrWhiteSpace(this.Manifest))
{
return new UniversalPackageMetadata
{
Group = this.Group,
Name = this.Name,
Version = UniversalPackageVersion.TryParse(this.NewVersion),
Title = this.Title,
Description = this.PackageDescription,
Icon = this.IconUrl
};
}
else
{
try
{
using var metadataStream = File.OpenRead(this.Manifest);
return UniversalPackageMetadata.Parse(metadataStream);
}
catch (Exception ex)
{
throw new UpackException($"The manifest file '{this.Manifest}' does not exist or could not be opened.", ex);
}
}
}
#pragma warning restore CS0612 // Type or member is obsolete
}
}