Skip to content

Commit

Permalink
Add the build flag useNixCaseHack and set it on Darwin
Browse files Browse the repository at this point in the history
This build flag allows to publish an image on a case insensitive
FS. Otherwise, hash can differs as detailled in
#37

Fixes !37
  • Loading branch information
nlewo committed Oct 28, 2022
1 parent 6d36479 commit 37f96bf
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 7 deletions.
7 changes: 6 additions & 1 deletion default.nix
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{ pkgs ? import <nixpkgs> { } }:
{ pkgs ? import <nixpkgs> { }, system }:
let
l = pkgs.lib // builtins;

Expand All @@ -21,9 +21,14 @@ let
);
};
vendorSha256 = "sha256-/j4ZHOwU5Xi8CE/fHha+2iZhsLd/y2ovzVhvg8HDV78=";
ldflags = pkgs.lib.optional pkgs.stdenv.isDarwin [
"-X github.com/nlewo/nix2container/nix.useNixCaseHack=true"
];

};

skopeo-nix2container = pkgs.skopeo.overrideAttrs (old: {
EXTRA_LDFLAGS = pkgs.lib.optionalString pkgs.stdenv.isDarwin "-X github.com/nlewo/nix2container/nix.useNixCaseHack=true";
preBuild = let
patch = pkgs.fetchurl {
url = "https://github.com/Mic92/image/commit/b3cb51066518ed2c6f6c8cf0cb4ae1e84f68b5ce.patch";
Expand Down
2 changes: 1 addition & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
let
pkgs = nixpkgs.legacyPackages.${system};
nix2container = import ./. {
inherit pkgs;
inherit pkgs system;
};
examples = import ./examples {
inherit pkgs;
Expand Down
21 changes: 16 additions & 5 deletions nix/graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import (
"sort"
)

// On case insensitive FS (adfs on MacOS for instance), Nix adds a
// suffix to avoid filename collisions.
// See https://github.com/NixOS/nix/blob/ba9e69cdcd8022f37e344f2c86e60ee2b9da493f/src/libutil/archive.cc#L90
var useNixCaseHack string

type fileNode struct {
// The file name on the FS
srcPath string
Expand All @@ -35,15 +40,21 @@ func initGraph() *fileNode {
// file tree read on the FS. This means transformations are done during
// the graph construction.
func addFileToGraph(root *fileNode, path string, info *os.FileInfo, options *types.PathOptions) error {
pathInTar := filePathToTarPath(path, options)

dstPath := path
if useNixCaseHack != "" {
dstPath = removeNixCaseHackSuffix(dstPath)
}

dstPath = filePathToTarPath(dstPath, options)
// A regex in the options could make the path becoming the
// empty string. In this case, we don't want to create
// anything in the graph.
if pathInTar == "" {
if dstPath == "" {
return nil
}

parts := splitPath(pathInTar)
parts := splitPath(dstPath)
current := root
for _, part := range parts {
if node, exists := current.contents[part]; exists {
Expand All @@ -58,13 +69,13 @@ func addFileToGraph(root *fileNode, path string, info *os.FileInfo, options *typ

if current.srcPath != "" && current.srcPath != path {
return fmt.Errorf("The file '%s' already exists in the tar with source path %s but is added again with the source path %s",
pathInTar, current.srcPath, path)
dstPath, current.srcPath, path)
}
current.srcPath = path

if current.options != nil && !reflect.DeepEqual(current.options, options) {
return fmt.Errorf("The file '%s' already exists in the tar with options %#v but is overriden with options %#v",
pathInTar, current.options, options)
dstPath, current.options, options)
}
current.options = options

Expand Down
18 changes: 18 additions & 0 deletions nix/tar_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,21 @@ func TestTar(t *testing.T) {
t.Errorf("Size is %d while it should be %d", size, expectedSize)
}
}

func TestRemoveNixCaseHackSuffix(t *testing.T) {
ret := removeNixCaseHackSuffix("filename~nix~case~hack~1")
expected := "filename"
if ret != expected {
t.Errorf("%s should be %s", ret, expected)
}
ret = removeNixCaseHackSuffix("/path~nix~case~hack~1/filename")
expected = "/path/filename"
if ret != expected {
t.Errorf("%s should be %s", ret, expected)
}
ret = removeNixCaseHackSuffix("filename~nix~")
expected = "filename~nix~"
if ret != expected {
t.Errorf("%s should be %s", ret, expected)
}
}
20 changes: 20 additions & 0 deletions nix/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,31 @@ package nix

import (
"github.com/nlewo/nix2container/types"
"path"
"path/filepath"
"regexp"
"strings"
)

func removeNixCaseHackSuffix(filepath string) string {
caseHackSuffix := "~nix~case~hack~"
parts := strings.Split(filepath, "/")
cleaned := make([]string, len(parts))
for i, part := range parts {
idx := strings.Index(part, caseHackSuffix)
if idx != -1 {
cleaned[i] = part[0:idx]
} else {
cleaned[i] = part
}
}
var prefix string
if strings.HasPrefix(filepath, "/") {
prefix = "/"
}
return prefix + path.Join(cleaned...)
}

func splitPath(path string) []string {
cleaned := filepath.Clean(path)
parts := strings.Split(cleaned, "/")
Expand Down

0 comments on commit 37f96bf

Please sign in to comment.