Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add :deps/prep-lib support for git dependencies #7

Merged
merged 1 commit into from
Sep 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 52 additions & 21 deletions createHome.nix
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ let
};
};

handleGit = path: { url, rev, sha256, common_dir }: {
handleGit = path: { url, rev, sha256, common_dir, ... }: {
name = path;
path = pkgs.fetchgit {
inherit url rev sha256;
Expand All @@ -32,8 +32,10 @@ let
# Corresponds to the ~/.m2/repository directory
mavenRepoCache = pkgs.linkFarm "maven-repo-cache" (lib.mapAttrsToList fetchMaven contents.maven);

unpreppedGitWorkTrees = lib.mapAttrsToList handleGit contents.git;

# This corresponds to the ~/.gitlibs/libs directory, containing git worktrees
gitWorktreeCache = pkgs.linkFarm "git-worktree-cache" (lib.mapAttrsToList handleGit contents.git);
gitWorktreeCache = gitWorkTrees: pkgs.linkFarm "git-worktree-cache" gitWorkTrees;

# This corresponds to the ~/.gitlibs/_repos directory, containing git directories for the above worktrees
gitFakeRepoCache = pkgs.runCommandNoCC "git-fake-repo-cache" {}
Expand All @@ -56,24 +58,53 @@ let
echo '{}' > $out/tools/tools.edn
'';

# Creates the final home directory, combining all parts together
result = pkgs.linkFarm "clojure-home" [
{
name = ".m2/repository";
path = mavenRepoCache;
}
{
name = ".gitlibs/libs";
path = gitWorktreeCache;
}
{
name = ".gitlibs/_repos";
path = gitFakeRepoCache;
}
# Creates a home directory for Clojure, combining all parts together
clojureHome = gitWorkTrees:
pkgs.linkFarm "clojure-home" [
{
name = ".m2/repository";
path = mavenRepoCache;
}
{
name = ".gitlibs/libs";
path = gitWorktreeCache gitWorkTrees;
}
{
name = ".gitlibs/_repos";
path = gitFakeRepoCache;
}
{
name = ".clojure";
path = configDir;
}
];

unpreppedHome = clojureHome unpreppedGitWorkTrees;

utils = import ./utils.nix { inherit pkgs; };

prepLib = { path, name }: spec:
if spec ? prep then
let prep = spec.prep; in
pkgs.runCommand "${name}-prepped"
{ nativeBuildInputs = [ (utils.wrapClojure unpreppedHome pkgs.clojure) ]; }
''
cp -r ${path} $out
chmod -R +w $out
cd $out
clojure -X:${prep.alias} ${prep.fn}
''
else
path;

prepGitWorkTree = { name, ... }@wt:
{
name = ".clojure";
path = configDir;
}
];
inherit name;
path = prepLib wt (lib.getAttr name contents.git);
};

preppedGitWorkTrees = builtins.map prepGitWorkTree unpreppedGitWorkTrees;

preppedHome = clojureHome preppedGitWorkTrees;

in result
in preppedHome
28 changes: 6 additions & 22 deletions default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ let
# We don't care about lines being too long
flakeIgnore = [ "E501" ];
} ./locker.py;

utils = import ./utils.nix { inherit pkgs; };
in {
inherit standaloneLocker;

Expand All @@ -28,6 +30,7 @@ in {
commandLocker = command: pkgs.writeShellApplication {
name = "clojure-nix-locker";
runtimeInputs = [
pkgs.babashka
pkgs.coreutils
pkgs.git
pkgs.gnutar
Expand Down Expand Up @@ -70,26 +73,7 @@ in {
homeDirectory = import ./createHome.nix {
inherit pkgs src lockfile mavenRepos;
};
shellEnv = pkgs.writeTextFile {
name = "clojure-nix-locker.shell-env";
text = ''
export HOME="${homeDirectory}"
export JAVA_TOOL_OPTIONS="-Duser.home=${homeDirectory}"
'';
meta = {
description = ''
Can be sourced in shell scripts to export environment
variables so that `clojure` uses the locked dependencies.
'';
};
};
wrapClojure = clojure:
(pkgs.runCommandNoCC "locked-clojure" { buildInputs = [ pkgs.makeWrapper ]; } ''
mkdir -p $out/bin
makeWrapper ${clojure}/bin/clojure $out/bin/clojure \
--run "source ${shellEnv}"
makeWrapper ${clojure}/bin/clj $out/bin/clj \
--run "source ${shellEnv}"
'');
};
shellEnv = utils.shellEnv homeDirectory;
wrapClojure = utils.wrapClojure homeDirectory;
};
}
13 changes: 12 additions & 1 deletion locker.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,31 @@

gitlibsDir = args.home.joinpath('.gitlibs').resolve()

extractPrepLibInfo = '''
(some-> *input*
:deps/prep-lib
(select-keys [:alias :fn])
cheshire.core/generate-string
println)
whentze marked this conversation as resolved.
Show resolved Hide resolved
'''

if gitlibsDir.exists():
for namespace_path in gitlibsDir.joinpath('libs').iterdir():
for name_path in namespace_path.iterdir():
for rev_path in name_path.iterdir():
path = rev_path.relative_to(gitlibsDir, "libs").as_posix()
repo = Repo(rev_path)
prefetch = subprocess.run(["nix-prefetch-git", rev_path], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, check=True)

with open(rev_path / "deps.edn") as deps_edn:
prep = subprocess.run(["bb", "-I", "--stream", extractPrepLibInfo], stdin=deps_edn, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, check=True)
result['git'][path] = {
# This is the path to the corresponding bare repository in ~/.gitlibs/_repos
"common_dir": Path(repo.common_dir).resolve().relative_to(gitlibsDir, "_repos").as_posix(),
"url": repo.remotes.origin.url,
"rev": repo.head.commit.hexsha,
"sha256": json.loads(prefetch.stdout)['sha256'],
}
if preps := prep.stdout:
result['git'][path]['prep'] = json.loads(preps)
whentze marked this conversation as resolved.
Show resolved Hide resolved

print(json.dumps(result, indent=2, sort_keys=True))
25 changes: 25 additions & 0 deletions utils.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{ pkgs }:

rec {
shellEnv = homeDirectory: pkgs.writeTextFile {
name = "clojure-nix-locker.shell-env";
text = ''
export HOME="${homeDirectory}"
export JAVA_TOOL_OPTIONS="-Duser.home=${homeDirectory}"
'';
meta = {
description = ''
Can be sourced in shell scripts to export environment
variables so that `clojure` uses the locked dependencies.
'';
};
};
wrapClojure = homeDirectory: clojure:
(pkgs.runCommandNoCC "locked-clojure" { buildInputs = [ pkgs.makeWrapper ]; } ''
mkdir -p $out/bin
makeWrapper ${clojure}/bin/clojure $out/bin/clojure \
--run "source ${shellEnv homeDirectory}"
makeWrapper ${clojure}/bin/clj $out/bin/clj \
--run "source ${shellEnv homeDirectory}"
'');
}
whentze marked this conversation as resolved.
Show resolved Hide resolved