64 Commits

Author SHA1 Message Date
Igor Anić
9e47857ae9 fetch: make failing test 2024-04-09 15:00:21 +02:00
Ian Johnson
129de47a71 Fix first-time package fetches
Closes #19557
Closes #19561

Previously, `build.zig` was not being detected correctly by
`computeHash` for packages where there is a containing root directory.
2024-04-07 09:07:37 +02:00
Igor Anić
34bb670bb6 package manager: set executable bit
Based on file content. Detects elf magic header or shebang line.

Executable bit is ignored in hash calculation, as it was before this. So
packages hashes are not changed.

Reference:
https://github.com/ziglang/zig/issues/17463#issuecomment-1984798880

Fixes: 17463

Test is here:
7c4600d7bb/src/main.zig (L307)
(if #19500 got accepted I'll move this test to the Fetch.zig)
2024-04-06 13:00:57 -07:00
Igor Anić
a60b7af2c1 fetch: fix manifest included paths filtering
Filter should be applied on path where package root folder (if
there is any) is stripped. Manifest is inside package root and has paths
relative to package root not temporary directory root.
2024-04-04 01:59:15 +02:00
Igor Anić
8545cb0147 fetch: use package root detection pipeToFileSystem
Based on:
https://github.com/ziglang/zig/pull/19111#discussion_r1548620985

In pipeToFileSystem we are already iterating over all files in tarball.
Inspecting them there for existence of single root folder saves two
syscalls later.
2024-04-03 21:20:39 +02:00
Igor Anić
363acf4991 fetch: update comments 2024-04-03 21:17:57 +02:00
Igor Anić
1431e34cb9 fetch: remove one openDir in runResource
Based on comment:
https://github.com/ziglang/zig/pull/19111#discussion_r1548640939

computeHash finds all files in temporary directory. There is no
difference on what path are they. When calculating hash normalized_path
must be set relative to package root. That's the place where we strip
root if needed.
2024-04-03 21:01:29 +02:00
Igor Anić
24304a4385 fetch: save syscall, and add comment
From review comments: https://github.com/ziglang/zig/pull/19111
2024-04-03 17:08:41 +02:00
Igor Anić
c4261bf562 fetch: find package root only for archives 2024-04-03 17:06:20 +02:00
Igor Anić
15ca0c9471 fix typo 2024-04-03 17:06:20 +02:00
Igor Anić
a5a928b966 package manager: don't strip components in tar
Unpack tar without removing leading root folder. Then find package root
in unpacked tmp folder.
2024-04-03 17:06:20 +02:00
Igor Anić
bc5076715b fetch: fix failing test
Prior to
[this](ef9966c985 (diff-08c935ef8c633bb630641d44230597f1cff5afb0e736d451e2ba5569fa53d915R805))
commit tar was not a valid extension. After that this one is valid case.
2024-04-03 17:06:20 +02:00
Andrew Kelley
7bc0b74b6d move Package.Path to std.Build.Cache.Path 2024-03-21 16:16:47 -07:00
Andrew Kelley
cd62005f19 extract std.posix from std.os
closes #5019
2024-03-19 11:45:09 -07:00
Igor Anić
0cca7e732e std.tar: fix broken public interface 2024-03-11 12:25:51 +01:00
Andrew Kelley
d661f0f35b compiler: JIT zig fmt
See #19063
2024-02-26 22:26:19 -07:00
Andrew Kelley
08e886b8fe package management: fix regression of printing expected hash
Regressed in ed4ccea7bae99c1baa634716941f308d9f922985. The early exit
path was only supposed to happen in case of --system mode.
2024-02-25 09:27:39 -08:00
Andrew Kelley
c44a902836 fix zstd compilation errors from previous commit 2024-02-23 02:37:11 -07:00
dweiller
ac1b957e79 std.compress.zstd: remove allocation from DecompressStream 2024-02-23 02:37:11 -07:00
Andrew Kelley
4d401e6159 std.http: remove Headers API
I originally removed these in 402f967ed5339fa3d828b7fe1d57cdb5bf38dbf2.
I allowed them to be added back in #15299 because they were smuggled in
alongside a bug fix, however, I wasn't kidding when I said that I wanted
to take the design of std.http in a different direction than using this
data structure.

Instead, some headers are provided via explicit field names populated
while parsing the HTTP request/response, and some are provided via
new fields that support passing extra, arbitrary headers.

This resulted in simplification of logic in many places, as well as
elimination of the possibility of failure in many places. There is
less deinitialization code happening now.

Furthermore, it made it no longer necessary to clone the headers data
structure in order to handle redirects.

http_proxy and https_proxy fields are now pointers since it is common
for them to be unpopulated.

loadDefaultProxies is changed into initDefaultProxies to communicate
that it does not actually load anything from disk or from the network.
The function now is leaky; the API user must pass an already
instantiated arena allocator. Removes the need to deinitialize proxies.

Before, proxies stored arbitrary sets of headers. Now they only store
the authorization value.

Removed the duplicated code between https_proxy and http_proxy. Finally,
parsing failures of the environment variables result in errors being
emitted rather than silently ignoring the proxy.

error.CompressionNotSupported is renamed to
error.CompressionUnsupported, matching the naming convention from all
the other errors in the same set.

Removed documentation comments that were redundant with field and type
names.

Disabling zstd decompression in the server for now; see #18937.

I found some apparently dead code in src/Package/Fetch/git.zig. I want
to check with Ian about this.

I discovered that test/standalone/http.zig is dead code, it is only
being compiled but not being run. Furthermore it hangs at the end if you
run it manually. The previous commits in this branch were written under
the assumption that this test was being run with
`zig build test-standalone`.
2024-02-23 02:37:11 -07:00
Andrew Kelley
90bd4f226e std.http: remove the ability to heap-allocate headers
The buffer for HTTP headers is now always provided via a static buffer.
As a consequence, OutOfMemory is no longer a member of the read() error
set, and the API and implementation of Client and Server are simplified.

error.HttpHeadersExceededSizeLimit is renamed to
error.HttpHeadersOversize.
2024-02-23 02:37:10 -07:00
Igor Anić
d645114f7e add deflate implemented from first principles
Zig deflate compression/decompression implementation. It supports compression and decompression of gzip, zlib and raw deflate format.

Fixes #18062.

This PR replaces current compress/gzip and compress/zlib packages. Deflate package is renamed to flate. Flate is common name for deflate/inflate where deflate is compression and inflate decompression.

There are breaking change. Methods signatures are changed because of removal of the allocator, and I also unified API for all three namespaces (flate, gzip, zlib).

Currently I put old packages under v1 namespace they are still available as compress/v1/gzip, compress/v1/zlib, compress/v1/deflate. Idea is to give users of the current API little time to postpone analyzing what they had to change. Although that rises question when it is safe to remove that v1 namespace.

Here is current API in the compress package:

```Zig
// deflate
    fn compressor(allocator, writer, options) !Compressor(@TypeOf(writer))
    fn Compressor(comptime WriterType) type

    fn decompressor(allocator, reader, null) !Decompressor(@TypeOf(reader))
    fn Decompressor(comptime ReaderType: type) type

// gzip
    fn compress(allocator, writer, options) !Compress(@TypeOf(writer))
    fn Compress(comptime WriterType: type) type

    fn decompress(allocator, reader) !Decompress(@TypeOf(reader))
    fn Decompress(comptime ReaderType: type) type

// zlib
    fn compressStream(allocator, writer, options) !CompressStream(@TypeOf(writer))
    fn CompressStream(comptime WriterType: type) type

    fn decompressStream(allocator, reader) !DecompressStream(@TypeOf(reader))
    fn DecompressStream(comptime ReaderType: type) type

// xz
   fn decompress(allocator: Allocator, reader: anytype) !Decompress(@TypeOf(reader))
   fn Decompress(comptime ReaderType: type) type

// lzma
    fn decompress(allocator, reader) !Decompress(@TypeOf(reader))
    fn Decompress(comptime ReaderType: type) type

// lzma2
    fn decompress(allocator, reader, writer !void

// zstandard:
    fn DecompressStream(ReaderType, options) type
    fn decompressStream(allocator, reader) DecompressStream(@TypeOf(reader), .{})
    struct decompress
```

The proposed naming convention:
 - Compressor/Decompressor for functions which return type, like Reader/Writer/GeneralPurposeAllocator
 - compressor/compressor for functions which are initializers for that type, like reader/writer/allocator
 - compress/decompress for one shot operations, accepts reader/writer pair, like read/write/alloc

```Zig
/// Compress from reader and write compressed data to the writer.
fn compress(reader: anytype, writer: anytype, options: Options) !void

/// Create Compressor which outputs the writer.
fn compressor(writer: anytype, options: Options) !Compressor(@TypeOf(writer))

/// Compressor type
fn Compressor(comptime WriterType: type) type

/// Decompress from reader and write plain data to the writer.
fn decompress(reader: anytype, writer: anytype) !void

/// Create Decompressor which reads from reader.
fn decompressor(reader: anytype) Decompressor(@TypeOf(reader)

/// Decompressor type
fn Decompressor(comptime ReaderType: type) type

```

Comparing this implementation with the one we currently have in Zig's standard library (std).
Std is roughly 1.2-1.4 times slower in decompression, and 1.1-1.2 times slower in compression. Compressed sizes are pretty much same in both cases.
More resutls in [this](https://github.com/ianic/flate) repo.

This library uses static allocations for all structures, doesn't require allocator. That makes sense especially for deflate where all structures, internal buffers are allocated to the full size. Little less for inflate where we std version uses less memory by not preallocating to theoretical max size array which are usually not fully used.

For deflate this library allocates 395K while std 779K.
For inflate this library allocates 74.5K while std around 36K.

Inflate difference is because we here use 64K history instead of 32K in std.

If merged existing usage of compress gzip/zlib/deflate need some changes. Here is example with necessary changes in comments:

```Zig

const std = @import("std");

// To get this file:
// wget -nc -O war_and_peace.txt https://www.gutenberg.org/ebooks/2600.txt.utf-8
const data = @embedFile("war_and_peace.txt");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer std.debug.assert(gpa.deinit() == .ok);
    const allocator = gpa.allocator();

    try oldDeflate(allocator);
    try new(std.compress.flate, allocator);

    try oldZlib(allocator);
    try new(std.compress.zlib, allocator);

    try oldGzip(allocator);
    try new(std.compress.gzip, allocator);
}

pub fn new(comptime pkg: type, allocator: std.mem.Allocator) !void {
    var buf = std.ArrayList(u8).init(allocator);
    defer buf.deinit();

    // Compressor
    var cmp = try pkg.compressor(buf.writer(), .{});
    _ = try cmp.write(data);
    try cmp.finish();

    var fbs = std.io.fixedBufferStream(buf.items);
    // Decompressor
    var dcp = pkg.decompressor(fbs.reader());

    const plain = try dcp.reader().readAllAlloc(allocator, std.math.maxInt(usize));
    defer allocator.free(plain);
    try std.testing.expectEqualSlices(u8, data, plain);
}

pub fn oldDeflate(allocator: std.mem.Allocator) !void {
    const deflate = std.compress.v1.deflate;

    // Compressor
    var buf = std.ArrayList(u8).init(allocator);
    defer buf.deinit();
    // Remove allocator
    // Rename deflate -> flate
    var cmp = try deflate.compressor(allocator, buf.writer(), .{});
    _ = try cmp.write(data);
    try cmp.close(); // Rename to finish
    cmp.deinit(); // Remove

    // Decompressor
    var fbs = std.io.fixedBufferStream(buf.items);
    // Remove allocator and last param
    // Rename deflate -> flate
    // Remove try
    var dcp = try deflate.decompressor(allocator, fbs.reader(), null);
    defer dcp.deinit(); // Remove

    const plain = try dcp.reader().readAllAlloc(allocator, std.math.maxInt(usize));
    defer allocator.free(plain);
    try std.testing.expectEqualSlices(u8, data, plain);
}

pub fn oldZlib(allocator: std.mem.Allocator) !void {
    const zlib = std.compress.v1.zlib;

    var buf = std.ArrayList(u8).init(allocator);
    defer buf.deinit();

    // Compressor
    // Rename compressStream => compressor
    // Remove allocator
    var cmp = try zlib.compressStream(allocator, buf.writer(), .{});
    _ = try cmp.write(data);
    try cmp.finish();
    cmp.deinit(); // Remove

    var fbs = std.io.fixedBufferStream(buf.items);
    // Decompressor
    // decompressStream => decompressor
    // Remove allocator
    // Remove try
    var dcp = try zlib.decompressStream(allocator, fbs.reader());
    defer dcp.deinit(); // Remove

    const plain = try dcp.reader().readAllAlloc(allocator, std.math.maxInt(usize));
    defer allocator.free(plain);
    try std.testing.expectEqualSlices(u8, data, plain);
}

pub fn oldGzip(allocator: std.mem.Allocator) !void {
    const gzip = std.compress.v1.gzip;

    var buf = std.ArrayList(u8).init(allocator);
    defer buf.deinit();

    // Compressor
    // Rename compress => compressor
    // Remove allocator
    var cmp = try gzip.compress(allocator, buf.writer(), .{});
    _ = try cmp.write(data);
    try cmp.close(); // Rename to finisho
    cmp.deinit(); // Remove

    var fbs = std.io.fixedBufferStream(buf.items);
    // Decompressor
    // Rename decompress => decompressor
    // Remove allocator
    // Remove try
    var dcp = try gzip.decompress(allocator, fbs.reader());
    defer dcp.deinit(); // Remove

    const plain = try dcp.reader().readAllAlloc(allocator, std.math.maxInt(usize));
    defer allocator.free(plain);
    try std.testing.expectEqualSlices(u8, data, plain);
}

```
2024-02-14 18:28:20 +01:00
Andrew Kelley
d753c3a121 CLI: implement 'zig build' lazy dependency fetching
This makes `zig build` notice when lazy dependencies were missing, fetch
them, and then rebuild the build runner and run it again.
2024-02-02 20:43:01 -07:00
Andrew Kelley
252f4ab2a5 build system: implement lazy dependencies, part 1
Build manifest files support `lazy: true` for dependency sections.
This causes the auto-generated dependencies.zig to have 2 more
possibilities:
1. It communicates whether a dependency is lazy or not.
2. The dependency might be acknowledged, but missing due to being lazy
   and not fetched.

Lazy dependencies are not fetched by default, but if they are already
fetched then they are provided to the build script.

The build runner reports the set of missing lazy dependenices that are
required to the parent process via stdout and indicates the situation
with exit code 3.

std.Build now has a `lazyDependency` function. I'll let the doc comments
speak for themselves:

When this function is called, it means that the current build does, in
fact, require this dependency. If the dependency is already fetched, it
proceeds in the same manner as `dependency`. However if the dependency
was not fetched, then when the build script is finished running, the
build will not proceed to the make phase. Instead, the parent process
will additionally fetch all the lazy dependencies that were actually
required by running the build script, rebuild the build script, and then
run it again.
In other words, if this function returns `null` it means that the only
purpose of completing the configure phase is to find out all the other
lazy dependencies that are also required.
It is allowed to use this function for non-lazy dependencies, in which
case it will never return `null`. This allows toggling laziness via
build.zig.zon without changing build.zig logic.

The CLI for `zig build` detects this situation, but the logic for then
redoing the build process with these extra dependencies fetched is not
yet implemented.
2024-02-02 20:43:01 -07:00
Andrew Kelley
ed4ccea7ba build system: implement --system [dir]
This prevents package fetching and enables system_package_mode in the
build system which flips the defaults for system integrations.
2024-02-02 20:43:01 -07:00
Krzysztof Wolicki
14efbbfd89
std.Uri: change specifier for printing with scheme to semicolon ;
Fetch: print scheme when suggesting adding a ref to git URIs
2024-01-18 09:13:04 +02:00
cipharius
2e77956629 Accepts generic application/x-compressed in package fetch 2024-01-15 18:26:12 +02:00
Joel Gustafson
dbdee2d53c
ignore charset and boundary directives in content-type headers when fetching dependencies 2024-01-09 20:16:59 +00:00
Andrew Kelley
2a32264533 package fetching: catch relative paths that resolve into cache dir
The logic here already caught the case when a dependency path tried to
escape out of the zig cache directory using up directories. However, it
did not catch the case when the relative path tried to reach into a
different path within the zig-cache. For example, if it asked for
"../../../blah" then it would be caught, but if it asked for "../blah"
then it would try to resolve as "zig-cache/p/blah" and probably result
in file-not-found, or perhaps resolve to a different package if someone
inadvertently used a valid package hash instead of "blah".

Now it correctly gives a "dependency path outside project" error,
however, still allows relative paths with up-dirs that were not fetched
via URL.
2023-11-28 04:14:41 -05:00
Andrew Kelley
a0c8d54823 add Package.Manifest.copyErrorsIntoBundle 2023-11-26 19:41:00 -07:00
Andrew Kelley
e357550610 update for the std.fs.Dir changes 2023-11-22 15:24:57 -07:00
Tobias Simetsreiter
d1230842ac add Fetch support for short compressed tar ext
these short extensions are common in a lot of
places, and should be treated like their double
versions
2023-10-24 13:49:28 -04:00
Nameless
363d0ee5e1
std.http: rename start->send and request->open to be more inline with operation 2023-10-21 20:52:59 -05:00
dweiller
f58811a58a package fetching: support .tar.zst archives 2023-10-17 19:02:00 -04:00
Andrew Kelley
ba656e5c9f zig fetch: add --debug-hash argument
This argument causes zig to print verbose hashing information to stdout,
which can be used to diff two different fetches and find out why the
hashes do not equal each other.
2023-10-16 18:15:47 -07:00
Andrew Kelley
b171a6f25d Package.Fetch: normalize path separators in symlinks
closes #17549
2023-10-16 16:47:47 -07:00
Andrew Kelley
1d1e5a8617 Package.Fetch: fix empty path and "." not including all
Related to #17491
2023-10-12 10:47:22 -07:00
Krzysztof Wolicki
8c6b0271cc Package.Fetch: wrap operations involving tmp_directory in a block
This makes tmp_directory close before calling renameTmpIntoCache which fixes occurences of those AccessDenied errors that aren't synonymous with PathAlreadyExists on Windows
2023-10-11 20:28:07 -07:00
Andrew Kelley
2ca7cc46c4 Package.Fetch: fix inclusions not working for directories
Oops, the loop was checking the wrong variable! Added a unit test.
2023-10-10 02:29:29 -07:00
Andrew Kelley
fa08e49f83 Package.Fetch: allow relative paths outside project root
Only for packages that come from the main package. Fetched packages
still cannot depend on paths outside their package root.
2023-10-09 22:01:18 -07:00
Andrew Kelley
95907cb795 restore progress reporting for package fetching 2023-10-08 21:14:30 -07:00
Andrew Kelley
cd4397783f Package.Fetch: improved deletion algorithm
Instead of every file deletion being followed by a recursive attempt to
remove the parent directory, while walking the directory, every
directory that will have nonzero files deleted from it is tracked in an
array hash map.

After all the threads have finished deleting and hashing, the parent
thread sorts the "suspicious" directories by length, descending,
ensuring that children appear before parents, and then iterates over the
array hash map, attempting a rmdir operation on each. Any rmdir that
succeeds appends the parent directory to the map so that it will be
removed if empty.
2023-10-08 20:03:40 -07:00
Andrew Kelley
4a2cf38844 Package.Fetch: apply inclusion rules from build.zig.zon 2023-10-08 19:29:17 -07:00
Andrew Kelley
5e7c44a321 Package.Fetch: tighten up check for path outside root 2023-10-08 17:42:49 -07:00
Andrew Kelley
6d84caf727 move some package management related source files around 2023-10-08 17:29:55 -07:00
Andrew Kelley
7bae6d9064 fix dependencies.zig generation with no dependencies 2023-10-08 17:26:02 -07:00
Andrew Kelley
f0cc6f17a0 Package.Fetch: fix not making directory paths for symlinks 2023-10-08 17:21:08 -07:00
Andrew Kelley
1ad33f53fe give build.zig modules access to their dependencies' build.zig modules 2023-10-08 16:54:31 -07:00
Andrew Kelley
47a413361d Package.Fetch: fix handling of relative paths 2023-10-08 16:54:31 -07:00
Andrew Kelley
1fd95fc005 Package.Fetch: resolve instead of join relative paths
This prevents bogus "error: file exists in multiple modules" errors due
to file paths looking like:
```
note: root of module foo/freetype/
note: root of module foo/fontconfig/../freetype/
```

It also enables checking for dependency paths outside the root package.
2023-10-08 16:54:31 -07:00