-
Notifications
You must be signed in to change notification settings - Fork 21
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 support for automatically gitignoring generated files #157
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,6 @@ | ||
########## | ||
# This file is autogenerated by Organist, don't edit | ||
########## | ||
.editorconfig | ||
/examples/*/result | ||
/result |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
let nix = import "./nix-interop/nix.ncl" in | ||
{ | ||
File = { | ||
target | ||
| doc m%" | ||
The file to write to. | ||
If null, defaults to the attribute name of the file. | ||
"% | ||
| String | ||
| optional, | ||
content | ||
| doc m%" | ||
The content of the file. | ||
"% | ||
| nix.derivation.NixString, | ||
materialisation_method | ||
: [| 'Symlink, 'Copy |] | ||
| doc m%" | ||
How the file should be materialized on-disk. | ||
|
||
Symlinking makes it easier to track where the files are coming from, | ||
but their target only exists after a first call to Organist, which | ||
might be undesirable. | ||
"% | ||
| default | ||
= 'Copy, | ||
.. | ||
}, | ||
Files = { _ : File }, | ||
NormaliseTargets = fun label files => | ||
files | ||
|> std.record.map (fun name file_descr => file_descr & { target | default = name }), | ||
|
||
Schema = { | ||
files | ||
| Files | ||
| NormaliseTargets | ||
| doc m%" | ||
Set of files that should be generated in the project's directory. | ||
"% | ||
= {}, | ||
flake.apps.regenerate-files.program = nix-s%"%{regenerate_files files}/bin/regenerate-files"%, | ||
}, | ||
|
||
regenerate_files | Files -> nix.derivation.Derivation = fun files_to_generate => | ||
let regnerate_one | String -> File -> nix.derivation.NixString = fun key file_descr => | ||
let file_content = file_descr.content in | ||
let target = file_descr.target in | ||
let copy_command = | ||
match { | ||
'Symlink => "ln -s", | ||
'Copy => "cp", | ||
} | ||
file_descr.materialisation_method | ||
in | ||
let file_in_store = | ||
nix.builtins.to_file | ||
(nix.utils.escape_drv_name key) | ||
file_content | ||
in | ||
nix-s%" | ||
rm -f %{target} | ||
echo "Regenerating %{target}" | ||
%{copy_command} %{file_in_store} %{target} | ||
"% | ||
in | ||
{ | ||
name = "regenerate-files", | ||
content.text = | ||
files_to_generate | ||
|> std.record.to_array | ||
|> std.array.map (fun { field, value } => regnerate_one field value) | ||
|> std.array.fold_left | ||
( | ||
fun acc elt => | ||
nix-s%" | ||
%{acc} | ||
%{elt} | ||
"% | ||
) | ||
"", | ||
} | ||
| nix.builders.ShellApplication, | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# let nix = import "./nix-interop/nix.ncl" in | ||
let filegen = import "./files.ncl" in | ||
let Gitignorable = { | ||
gitignore | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should probably be nested like |
||
: Bool | ||
| doc "Whether to gitignore the file" | ||
| default | ||
= false, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This means that each generated file will be added to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No they aren't, the ones with But that indeed makes some slightly confusing semantics as it means that |
||
.. | ||
} | ||
in | ||
let header : String = m%" | ||
########## | ||
# This file is autogenerated by Organist, don't edit | ||
########## | ||
|
||
"% | ||
in | ||
let ignored_files | { _ : Gitignorable } -> { _ : Bool } = fun files => | ||
files | ||
|> std.record.to_array | ||
|> std.array.filter (fun { value = { gitignore, .. }, .. } => gitignore) | ||
|> std.array.map (fun { value = { target, .. }, .. } => { field = target, value = true }) | ||
|> std.record.from_array | ||
in | ||
let gitignore_content | { _ : Bool } -> String = fun ignores => | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think these functions should be in the final record so that users can add more |
||
ignores | ||
|> std.record.map | ||
( | ||
fun pattern is_ignored => | ||
"%{if is_ignored then "" else "!"}%{pattern}" | ||
) | ||
|> std.record.values | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should somehow provide a way to order these lines, because order is important in |
||
|> std.string.join "\n" | ||
|> (fun c => header ++ c ++ "\n") | ||
in | ||
{ | ||
Schema = | ||
filegen.Schema | ||
& { | ||
|
||
files | filegen.Files, | ||
files | { _ : Gitignorable }, | ||
|
||
git.ignore | ||
| { _ : Bool } | ||
= ignored_files files, | ||
|
||
files.".gitignore".materialisation_method = 'Copy, | ||
files.".gitignore".content = gitignore_content git.ignore, | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
escape_drv_name | ||
: String -> String | ||
| doc m%" | ||
Escape the given string to make it an allowed derivation name | ||
"% | ||
= fun str => | ||
if std.string.is_match "^\\." str then | ||
"-" ++ str | ||
else | ||
str | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.