Skip to content

Commit

Permalink
disallow using Zig master/nightly with a tagged release of ZLS
Browse files Browse the repository at this point in the history
This change will not affect development builds of ZLS.
  • Loading branch information
Techatrix committed Jan 15, 2025
1 parent 3ca6f2a commit f6e9d58
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 36 deletions.
16 changes: 13 additions & 3 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,7 @@ const Build = blk: {
std.debug.assert(zls_version.pre == null or std.mem.eql(u8, zls_version.pre.?, "dev"));
std.debug.assert(zls_version.build == null);
const zls_version_is_tagged = zls_version.pre == null and zls_version.build == null;
const zls_version_simple: std.SemanticVersion = .{ .major = zls_version.major, .minor = zls_version.minor, .patch = 0 };

if (min_runtime_zig.order(min_build_zig) == .gt) {
const message = std.fmt.comptimePrint(
Expand All @@ -546,19 +547,28 @@ const Build = blk: {

// check that the ZLS version and minimum build version make sense
if (zls_version_is_tagged) {
if (zls_version.order(min_build_zig) != .eq) {
if (zls_version_simple.order(min_build_zig) != .eq) {
const message = std.fmt.comptimePrint(
\\A tagged release of ZLS should have the same tagged release of Zig as the minimum build requirement:
\\ ZLS version: {[current_version]}
\\ minimum Zig version: {[minimum_version]}
\\
\\This is a developer error. Set `minimum_build_zig_version` in `build.zig` and `minimum_zig_version` in `build.zig.zon` to {[current_version]}.
, .{ .current_version = zls_version, .minimum_version = min_build_zig });
, .{ .current_version = zls_version_simple, .minimum_version = min_build_zig });
@compileError(message);
}
if (zls_version_simple.order(min_runtime_zig) != .eq) {
const message = std.fmt.comptimePrint(
\\A tagged release of ZLS should have the same tagged release of Zig as the minimum runtime version:
\\ ZLS version: {[current_version]}
\\ minimum Zig version: {[minimum_version]}
\\
\\This is a developer error. Set `minimum_runtime_zig_version` in `build.zig` to `{[current_version]}`.
, .{ .current_version = zls_version_simple, .minimum_version = min_runtime_zig });
@compileError(message);
}
} else {
const min_build_zig_simple: std.SemanticVersion = .{ .major = min_build_zig.major, .minor = min_build_zig.minor, .patch = 0 };
const zls_version_simple: std.SemanticVersion = .{ .major = zls_version.major, .minor = zls_version.minor, .patch = 0 };
const min_zig_is_tagged = min_build_zig.build == null and min_build_zig.pre == null;
if (!min_zig_is_tagged and zls_version_simple.order(min_build_zig_simple) != .eq) {
const message = std.fmt.comptimePrint(
Expand Down
162 changes: 129 additions & 33 deletions src/build_runner/BuildRunnerVersion.zig
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,24 @@ pub const BuildRunnerVersion = enum {
}

pub fn selectBuildRunnerVersion(runtime_zig_version: std.SemanticVersion) ?BuildRunnerVersion {
const minimum_runtime_zig_version = comptime std.SemanticVersion.parse(build_options.minimum_runtime_zig_version_string) catch unreachable;
return selectVersionInternal(BuildRunnerVersion, minimum_runtime_zig_version, runtime_zig_version);
const is_zls_version_tagged = build_options.version.pre == null and build_options.version.build == null;
if (is_zls_version_tagged) {
// A ZLS release should not have a 'master.zig' build runner.
// To fix this, rename it to `${ZLS_VERSION}.zig` and remove all outdated version checks from it.
comptime std.debug.assert(!@hasField(BuildRunnerVersion, "master"));
}

const min_runtime_zig_version = comptime std.SemanticVersion.parse(build_options.minimum_runtime_zig_version_string) catch unreachable;
return selectVersionInternal(
BuildRunnerVersion,
// If ZLS is a tagged release, it should not support development builds of the next release cycle. Example:
// - ZLS `0.13.0` with Zig `0.13.0` -> ok
// - ZLS `0.13.0` with Zig `0.14.0-dev` -> bad
// - ZLS `0.14.0-dev` with Zig `0.13.0` -> check `minimum_runtime_zig_version`
// - ZLS `0.14.0-dev` with Zig `0.14.0-dev` -> check `minimum_runtime_zig_version`
if (!is_zls_version_tagged) min_runtime_zig_version else null,
runtime_zig_version,
);
}

pub fn getBuildRunnerFile(version: BuildRunnerVersion) [:0]const u8 {
Expand All @@ -28,12 +44,15 @@ pub const BuildRunnerVersion = enum {

fn selectVersionInternal(
comptime AvailableVersion: type,
/// Only relevant when the ZLS version is a development build
comptime minimum_runtime_zig_version: std.SemanticVersion,
/// If set, a non-tagged `runtime_zig_version` must be at least the specified version.
/// If unset, a non-tagged `runtime_zig_version` will return `null`.
/// Will be ignored if the `runtime_zig_version` is a tagged release.
///
/// Will be `null` iff ZLS is a tagged release.
comptime minimum_runtime_zig_version: ?std.SemanticVersion,
runtime_zig_version: std.SemanticVersion,
) ?AvailableVersion {
const runtime_zig_version_is_tagged = runtime_zig_version.build == null and runtime_zig_version.pre == null;
const minimum_runtime_zig_version_is_tagged = minimum_runtime_zig_version.build == null and minimum_runtime_zig_version.pre == null;

const available_version_tags = comptime std.meta.tags(AvailableVersion);
// `null` means master
Expand All @@ -53,7 +72,6 @@ fn selectVersionInternal(
comptime {
std.debug.assert(available_version_tags.len != 0);
std.debug.assert(available_version_tags.len == available_versions.len);
std.debug.assert(minimum_runtime_zig_version_is_tagged == !@hasField(AvailableVersion, "master"));
}

if (runtime_zig_version_is_tagged) {
Expand All @@ -65,16 +83,25 @@ fn selectVersionInternal(
}
}
return null;
}
} else if (minimum_runtime_zig_version) |min_runtime_zig_version| {
const min_runtime_zig_version_is_tagged = min_runtime_zig_version.build == null and min_runtime_zig_version.pre == null;
// There are two allowed states:
// - the minimum runtime zig version is a development build and a 'master' build runner is available
// - the minimum runtime zig version is a tagged release and no 'master' build runner is available
comptime std.debug.assert(min_runtime_zig_version_is_tagged == !@hasField(AvailableVersion, "master"));

switch (runtime_zig_version.order(available_versions[0] orelse minimum_runtime_zig_version)) {
.eq, .gt => return available_version_tags[0],
.lt => return null,
switch (runtime_zig_version.order(available_versions[0] orelse min_runtime_zig_version)) {
.eq, .gt => return available_version_tags[0],
.lt => return null,
}
} else {
comptime std.debug.assert(!@hasField(AvailableVersion, "master"));
return null;
}
}

test selectVersionInternal {
@setEvalBranchQuota(6_000);
@setEvalBranchQuota(10_000);
const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;
const parse = std.SemanticVersion.parse;
Expand Down Expand Up @@ -160,70 +187,94 @@ test selectVersionInternal {

try expectEqual(null, selectVersionInternal(
AvailableVersion, // available build runners
try parse("0.11.0"), // minimum Zig version on master
null,
try parse("0.10.0"), // Zig version
));
try expectEqual(null, selectVersionInternal(
AvailableVersion, // available build runners
null,
try parse("0.11.0-dev.1+aaaaaaaaa"), // Zig version
));
try expectEqual(.@"0.11.0", selectVersionInternal(
AvailableVersion, // available build runners
try parse("0.11.0"), // minimum Zig version on master
null,
try parse("0.11.0"), // Zig version
));
try expectEqual(null, selectVersionInternal(
AvailableVersion, // available build runners
try parse("0.11.0"), // minimum Zig version on master
null,
try parse("0.12.0-dev.1+aaaaaaaaa"), // Zig version
));
try expectEqual(.@"0.12.0", selectVersionInternal(
AvailableVersion, // available build runners
try parse("0.11.0"), // minimum Zig version on master
null,
try parse("0.12.0"), // Zig version
));

try expectEqual(.@"0.12.0", selectVersionInternal(
AvailableVersion, // available build runners
null,
try parse("0.12.0"), // Zig version
));
try expectEqual(.@"0.12.0", selectVersionInternal(
AvailableVersion, // available build runners
null,
try parse("0.12.1"), // Zig version
));
try expectEqual(null, selectVersionInternal(
AvailableVersion, // available build runners
try parse("0.12.0"), // minimum Zig version on master
try parse("0.10.0"), // Zig version
null,
try parse("0.13.0-dev.1+aaaaaaaaa"), // Zig version
));
try expectEqual(null, selectVersionInternal(
AvailableVersion, // available build runners
try parse("0.12.0"), // minimum Zig version on master
try parse("0.11.0-dev.1+aaaaaaaaa"), // Zig version
null,
try parse("0.13.0"), // Zig version
));
try expectEqual(.@"0.11.0", selectVersionInternal(
}

{
const AvailableVersion = enum { @"0.12.0" };

try expectEqual(null, selectVersionInternal(
AvailableVersion, // available build runners
try parse("0.12.0"), // minimum Zig version on master
try parse("0.11.0"), // Zig version
try parse("0.12.0"), // minimum Zig version
try parse("0.11.0-dev.5+aaaaaaaaa"), // Zig version
));
try expectEqual(null, selectVersionInternal(
AvailableVersion, // available build runners
try parse("0.12.0"), // minimum Zig version on master
try parse("0.12.0-dev.1+aaaaaaaaa"), // Zig version
try parse("0.12.0"), // minimum Zig version
try parse("0.11.0"), // Zig version
));
try expectEqual(.@"0.12.0", selectVersionInternal(
try expectEqual(null, selectVersionInternal(
AvailableVersion, // available build runners
try parse("0.12.0"), // minimum Zig version on master
try parse("0.12.0"), // Zig version
try parse("0.12.0"), // minimum Zig version
try parse("0.12.0-dev.5+aaaaaaaaa"), // Zig version
));
try expectEqual(.@"0.12.0", selectVersionInternal(
AvailableVersion, // available build runners
try parse("0.12.0"), // minimum Zig version on master
try parse("0.12.0"), // minimum Zig version
try parse("0.12.0"), // Zig version
));
try expectEqual(.@"0.12.0", selectVersionInternal(
AvailableVersion, // available build runners
try parse("0.12.0"), // minimum Zig version on master
try parse("0.12.0"), // minimum Zig version
try parse("0.12.1"), // Zig version
));
try expectEqual(.@"0.12.0", selectVersionInternal(
AvailableVersion, // available build runners
try parse("0.12.0"), // minimum Zig version on master
try parse("0.13.0-dev.1+aaaaaaaaa"), // Zig version
try parse("0.12.0"), // minimum Zig version
try parse("0.13.0-dev.5+aaaaaaaaa"), // Zig version
));
try expectEqual(null, selectVersionInternal(
AvailableVersion, // available build runners
try parse("0.12.0"), // minimum Zig version on master
try parse("0.12.0"), // minimum Zig version
try parse("0.13.0"), // Zig version
));
try expectEqual(null, selectVersionInternal(
AvailableVersion, // available build runners
try parse("0.12.0"), // minimum Zig version
try parse("0.13.1"), // Zig version
));
}

{
Expand Down Expand Up @@ -280,4 +331,49 @@ test selectVersionInternal {
try parse("0.13.1"), // Zig version
));
}

{
const AvailableVersion = enum { master };

try expectEqual(null, selectVersionInternal(
AvailableVersion, // available build runners
try parse("0.13.0-dev.5+aaaaaaaaa"), // minimum Zig version on master
try parse("0.12.0-dev.5+aaaaaaaaa"), // Zig version
));
try expectEqual(null, selectVersionInternal(
AvailableVersion, // available build runners
try parse("0.13.0-dev.5+aaaaaaaaa"), // minimum Zig version on master
try parse("0.12.0"), // Zig version
));
try expectEqual(null, selectVersionInternal(
AvailableVersion, // available build runners
try parse("0.13.0-dev.5+aaaaaaaaa"), // minimum Zig version on master
try parse("0.12.1"), // Zig version
));
try expectEqual(null, selectVersionInternal(
AvailableVersion, // available build runners
try parse("0.13.0-dev.5+aaaaaaaaa"), // minimum Zig version on master
try parse("0.13.0-dev.4+aaaaaaaaa"), // Zig version
));
try expectEqual(.master, selectVersionInternal(
AvailableVersion, // available build runners
try parse("0.13.0-dev.5+aaaaaaaaa"), // minimum Zig version on master
try parse("0.13.0-dev.5+aaaaaaaaa"), // Zig version
));
try expectEqual(.master, selectVersionInternal(
AvailableVersion, // available build runners
try parse("0.13.0-dev.5+aaaaaaaaa"), // minimum Zig version on master
try parse("0.13.0-dev.10+aaaaaaaaa"), // Zig version
));
try expectEqual(null, selectVersionInternal(
AvailableVersion, // available build runners
try parse("0.13.0-dev.5+aaaaaaaaa"), // minimum Zig version on master
try parse("0.13.0"), // Zig version
));
try expectEqual(null, selectVersionInternal(
AvailableVersion, // available build runners
try parse("0.13.0-dev.5+aaaaaaaaa"), // minimum Zig version on master
try parse("0.13.1"), // Zig version
));
}
}

0 comments on commit f6e9d58

Please sign in to comment.