Skip to content

Commit 06c5a2b

Browse files
authored
Refactor deb packaging to DivineBytes and fix tar integrity (#142)
* Refactor deb packaging to DivineBytes and fix tar integrity * Stream ar byte source instead of buffering
1 parent 1d62b09 commit 06c5a2b

27 files changed

+433
-446
lines changed
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-

2-
using Zafiro.FileSystem.Readonly;
1+
using DotnetPackaging.Deb.Archives.Tar;
2+
using Zafiro.DivineBytes;
33

44
namespace DotnetPackaging.Deb.Archives.Ar;
55

6-
public record ArFile(params Entry[] Entries);
6+
public record ArFile(params ArEntry[] Entries);
77

8-
public record Entry(IFile File, Properties Properties);
8+
public record ArEntry(string Name, IByteSource Content, UnixFileProperties Properties);
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using System.Linq;
2+
using System.Reactive.Linq;
3+
using System.Text;
4+
using Zafiro.DivineBytes;
5+
using Zafiro.Mixins;
6+
7+
namespace DotnetPackaging.Deb.Archives.Ar;
8+
9+
public static class ArFileExtensions
10+
{
11+
private const string Signature = "!<arch>\n";
12+
13+
public static IByteSource ToByteSource(this ArFile arFile)
14+
{
15+
var parts = new List<IObservable<byte[]>> { ByteSource.FromString(Signature, Encoding.ASCII).Bytes };
16+
17+
foreach (var entry in arFile.Entries)
18+
{
19+
var size = entry.Content.GetSize().GetAwaiter().GetResult();
20+
var header = BuildHeader(entry, size);
21+
22+
parts.Add(ByteSource.FromString(header, Encoding.ASCII).Bytes);
23+
parts.Add(entry.Content.Bytes);
24+
25+
if (size % 2 != 0)
26+
{
27+
parts.Add(ByteSource.FromBytes(new[] { (byte)'\n' }).Bytes);
28+
}
29+
}
30+
31+
return ByteSource.FromByteObservable(parts.Aggregate(Observable.Concat));
32+
}
33+
34+
private static string BuildHeader(ArEntry entry, long size)
35+
{
36+
var modeOctal = Convert.ToString(entry.Properties.Mode, 8);
37+
38+
return
39+
$"{Field(entry.Name, 16)}" +
40+
$"{Field(entry.Properties.LastModification.ToUnixTimeSeconds().ToString(), 12)}" +
41+
$"{Field(entry.Properties.OwnerId.ToString(), 6)}" +
42+
$"{Field(entry.Properties.GroupId.ToString(), 6)}" +
43+
$"{Field($"100{modeOctal}", 8)}" +
44+
$"{Field(size.ToString(), 10)}" +
45+
"`\n";
46+
}
47+
48+
private static string Field(string value, int width)
49+
{
50+
if (value.Length > width)
51+
{
52+
return value[..width];
53+
}
54+
55+
return value.PadRight(width);
56+
}
57+
}

src/DotnetPackaging.Deb/Archives/Ar/ArFileMixin.cs

Lines changed: 0 additions & 17 deletions
This file was deleted.

src/DotnetPackaging.Deb/Archives/Ar/EntryMixin.cs

Lines changed: 0 additions & 37 deletions
This file was deleted.

src/DotnetPackaging.Deb/Archives/Ar/Properties.cs

Lines changed: 0 additions & 11 deletions
This file was deleted.
Lines changed: 31 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,47 @@
11
using CSharpFunctionalExtensions;
22
using DotnetPackaging.Deb.Archives.Ar;
33
using DotnetPackaging.Deb.Archives.Tar;
4-
using Zafiro.DataModel;
5-
using Zafiro.FileSystem.Unix;
6-
using File = Zafiro.FileSystem.Readonly.File;
4+
using Zafiro.DivineBytes;
5+
using Zafiro.Mixins;
76

87
namespace DotnetPackaging.Deb.Archives.Deb;
98

109
public static class DebMixin
1110
{
12-
public static IData ToData(this DebFile debFile)
11+
public static IByteSource ToByteSource(this DebFile debFile)
1312
{
1413
ArFile arFile = new ArFile(Signature(debFile), ControlTar(debFile), DataTar(debFile));
15-
return arFile.ToData();
14+
return arFile.ToByteSource();
1615
}
1716

18-
private static Entry DataTar(DebFile debFile)
17+
private static ArEntry DataTar(DebFile debFile)
1918
{
2019
TarFile dataTarFile = new TarFile(debFile.Entries);
21-
var properties = new Properties()
22-
{
23-
FileMode = "644".ToFileMode(),
24-
GroupId = 0,
25-
LastModification = debFile.Metadata.ModificationTime,
26-
OwnerId = 0,
27-
};
28-
return new Entry(new File("data.tar", dataTarFile.ToData()), properties);
20+
var properties = DefaultProperties(debFile);
21+
return new ArEntry("data.tar", dataTarFile.ToByteSource(), properties);
2922
}
3023

31-
private static Entry Signature(DebFile debFile)
24+
private static ArEntry Signature(DebFile debFile)
3225
{
33-
var properties = new Properties()
34-
{
35-
FileMode = "644".ToFileMode(),
36-
GroupId = 0,
37-
LastModification = debFile.Metadata.ModificationTime,
38-
OwnerId = 0,
39-
};
40-
41-
var signature = """
42-
2.0
26+
var properties = DefaultProperties(debFile);
4327

44-
""".FromCrLfToLf();
28+
var signature = "2.0\n";
4529

46-
return new Entry(new File("debian-binary", Data.FromString(signature)), properties);
30+
return new ArEntry("debian-binary", ByteSource.FromString(signature), properties);
4731
}
4832

49-
private static Entry ControlTar(DebFile debFile)
33+
private static ArEntry ControlTar(DebFile debFile)
5034
{
51-
var properties = new Properties()
52-
{
53-
FileMode = "644".ToFileMode(),
54-
GroupId = 0,
55-
LastModification = debFile.Metadata.ModificationTime,
56-
OwnerId = 0,
57-
};
58-
35+
var properties = DefaultProperties(debFile);
5936
var controlTarFile = ControlTarFile(debFile);
60-
return new Entry(new File("control.tar", controlTarFile.ToData()), properties);
37+
return new ArEntry("control.tar", controlTarFile.ToByteSource(), properties);
6138
}
6239

6340
private static TarFile ControlTarFile(DebFile deb)
6441
{
6542
var fileProperties = new TarFileProperties()
6643
{
67-
FileMode = "644".ToFileMode(),
44+
Mode = UnixPermissions.Parse("644"),
6845
GroupId = 0,
6946
GroupName = "root",
7047
OwnerId = 0,
@@ -74,7 +51,7 @@ private static TarFile ControlTarFile(DebFile deb)
7451

7552
var dirProperties = new TarDirectoryProperties()
7653
{
77-
FileMode = "755".ToFileMode(),
54+
Mode = UnixPermissions.Parse("755"),
7855
GroupId = 0,
7956
GroupName = "root",
8057
OwnerId = 0,
@@ -95,7 +72,7 @@ private static TarFile ControlTarFile(DebFile deb)
9572

9673
var content = items.Compose() + "\n";
9774

98-
var file = new File("control", Data.FromString(content));
75+
var file = ByteSource.FromString(content);
9976

10077
var entries = new TarEntry[]
10178
{
@@ -114,4 +91,17 @@ private static TarFile ControlTarFile(DebFile deb)
11491
var controlTarFile = new TarFile(entries.ToArray());
11592
return controlTarFile;
11693
}
117-
}
94+
95+
private static UnixFileProperties DefaultProperties(DebFile debFile)
96+
{
97+
return new UnixFileProperties
98+
{
99+
Mode = UnixPermissions.Parse("644"),
100+
GroupId = 0,
101+
OwnerId = 0,
102+
GroupName = "root",
103+
OwnerUsername = "root",
104+
LastModification = debFile.Metadata.ModificationTime
105+
};
106+
}
107+
}

src/DotnetPackaging.Deb/Archives/Tar/ByteProviderMixin.cs

Lines changed: 0 additions & 11 deletions
This file was deleted.
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
using Zafiro.DataModel;
1+
using Zafiro.DivineBytes;
22

33
namespace DotnetPackaging.Deb.Archives.Tar;
44

55
public record FileTarEntry : TarEntry
66
{
7-
public IData Content { get; }
7+
public IByteSource Content { get; }
88

9-
public FileTarEntry(string path, IData content, TarFileProperties properties) : base(path, properties)
9+
public FileTarEntry(string path, IByteSource content, TarFileProperties properties) : base(path, properties)
1010
{
1111
Content = content;
1212
}
13-
}
13+
}
Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
1-
using Zafiro.FileSystem.Unix;
1+
namespace DotnetPackaging.Deb.Archives.Tar;
22

3-
namespace DotnetPackaging.Deb.Archives.Tar;
4-
5-
public class Misc
3+
public static class Misc
64
{
75
public static TarFileProperties RegularFileProperties() => new()
86
{
9-
FileMode = "644".ToFileMode(),
7+
Mode = UnixPermissions.Parse("644"),
108
GroupId = 1000,
119
OwnerId = 1000,
1210
GroupName = "root",
1311
OwnerUsername = "root",
1412
LastModification = DateTimeOffset.Now
1513
};
1614

17-
public static TarFileProperties ExecutableFileProperties() => RegularFileProperties() with { FileMode = "755".ToFileMode() };
18-
}
15+
public static TarFileProperties ExecutableFileProperties() => RegularFileProperties() with { Mode = UnixPermissions.Parse("755") };
16+
}

src/DotnetPackaging.Deb/Archives/Tar/PaddingProvider.cs

Lines changed: 0 additions & 18 deletions
This file was deleted.

0 commit comments

Comments
 (0)