Giter VIP home page Giter VIP logo

niv's Introduction

niv

Test Netlify Status

Painless dependencies for Nix projects. Read more in the Getting started section below.

Install

niv is available in nixpkgs as niv:

$ nix-env -iA nixpkgs.niv

Alternatively, run the following command to install the development version:

$ nix-env -iA niv -f https://github.com/nmattia/niv/tarball/master \
    --substituters https://niv.cachix.org \
    --trusted-public-keys niv.cachix.org-1:X32PCg2e/zAm3/uD1ScqW2z/K0LtDyNV7RdaxIuLgQM=

Build

Inside the provided nix shell:

$ repl

Run the test suite with this command:

$ ./script/test

Usage

niv simplifies adding and updating dependencies in Nix projects. It uses a single file, nix/sources.json, where it stores the data necessary for fetching and updating the packages.

  • Add: inserts a package in nix/sources.json.
  • Update: updates one or all packages in nix/sources.json.
  • Drop: deletes a package from nix/sources.json.

niv has some utility functions:

  • Init: bootstraps a Nix project, in particular creates a nix/sources.json file containing niv and nixpkgs as well as a nix/sources.nix file that returns the sources as a Nix object.
  • Show: shows the packages' information.
  • Modify: modifies attributes without performing an update.

Configuration

The following environment variables are read by niv:

Name Note
GITHUB_TOKEN or NIV_GITHUB_TOKEN When set, the value is used to authenticate GitHub API requests.
GITHUB_HOST or NIV_GITHUB_HOST The GitHub host to use when fetching packages. Port may be appended here.
GITHUB_API_HOST or NIV_GITHUB_API_HOST The host used when performing GitHub API requests. Use GITHUB_API_PORT for specifying the port.
GITHUB_API_PORT or NIV_GITHUB_API_PORT The port used when performing GitHub API requests. Defaults to 443 for secure requests. Defaults to 80 for insecure requests. See also: GITHUB_INSECURE.
NIV_GITHUB_INSECURE When set to anything but the empty string, requests are performed over http instead of https.
NIV_GITHUB_PATH The base path used when performing GitHub API requests.

The next two sections cover common use cases and full command description.

Getting started

Nix is a very powerful tool for building code and setting up environments. niv complements it by making it easy to describe and update remote dependencies (URLs, GitHub repos, etc). It is a simple, practical alternative to Nix flakes.

This section covers common use cases:

Bootstrapping a Nix project

Use the init command when starting a new Nix project or when porting an existing Nix project to niv:

$ niv init
...
$ tree
.
└── nix
    ├── sources.json
    └── sources.nix

1 directory, 2 files

The file nix/sources.json is the file used by niv to store versions and is initialized with nixpkgs:

{
    "nixpkgs": {
        "branch": "nixos-unstable",
        "description": "Nix Packages collection",
        "homepage": null,
        "owner": "NixOS",
        "repo": "nixpkgs",
        "rev": "6c43a3495a11e261e5f41e5d7eda2d71dae1b2fe",
        "sha256": "16f329z831bq7l3wn1dfvbkh95l2gcggdwn6rk3cisdmv2aa3189",
        "type": "tarball",
        "url": "https://github.com/NixOS/nixpkgs/archive/6c43a3495a11e261e5f41e5d7eda2d71dae1b2fe.tar.gz",
        "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
    }
}

To use this dependency, import the file nix/sources.nix, e.g.:

{ sources ? import ./sources.nix }:     # import the sources
import sources.nixpkgs                  # and use them again!
  { overlays = [] ; config = {}; }

For more information about importing sources to your nix files, check the frequently asked questions.

Tracking a nixpkgs branch

The init command sets the nix/sources.json to the content of the file data/nixpkgs.json. Currently, you would be tracking the nixos-unstable branch. Run the following command to update it to the last commit of the configured branch:

$ niv update nixpkgs

To change the branch being tracked run this command:

$ niv update nixpkgs -b master     # equivalent to --branch master

Importing packages from GitHub

The add command will infer information about the package being added, when possible. This works very well for GitHub repositories. Run this command to add jq to your project:

$ niv add stedolan/jq

The following data was added in nix/sources.json for jq:

{
  "homepage": "http://stedolan.github.io/jq/",
  "url": "https://github.com/stedolan/jq/archive/9fa2e51099c55af56e3e541dc4b399f11de74abe.tar.gz",
  "owner": "stedolan",
  "branch": "master",
  "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz",
  "repo": "jq",
  "sha256": "0819rvk8057qgcqvgn7fpldvly2pfdw9fxcjrlqa8gr59p8a1cic",
  "description": "Command-line JSON processor",
  "rev": "9fa2e51099c55af56e3e541dc4b399f11de74abe"
}

Using custom URLs

It is possible to use niv to fetch packages from custom URLs. Run this command to add the Haskell compiler GHC to your nix/sources.json:

$ niv add ghc   \
    -v 8.4.3    \
    -t 'https://downloads.haskell.org/~ghc/<version>/ghc-<version>-i386-deb8-linux.tar.xz'

The option -v sets the "version" attribute to 8.4.3. The option -t sets a template that can be reused by niv when fetching a new URL (see the documentation for add and update).

The type of the dependency is guessed from the provided URL template, if -T is not specified.

For updating the version of GHC used run this command:

$ niv update ghc -v 8.6.2

Commands

niv - dependency manager for Nix projects

version: 0.2.22

Usage: niv [-s|--sources-file FILE] [--no-colors] COMMAND

Available options:
  -s,--sources-file FILE   Use FILE instead of nix/sources.json
  --no-colors              Don't use colors in output
  -h,--help                Show this help text
  --version                Print version

Available commands:
  init                     Initialize a Nix project. Existing files won't be
                           modified.
  add                      Add a GitHub dependency
  show                     
  update                   Update dependencies
  modify                   Modify dependency attributes without performing an
                           update
  drop                     Drop dependency

Add

Examples:

  niv add stedolan/jq
  niv add NixOS/nixpkgs -n nixpkgs -b nixpkgs-unstable
  niv add my-package -v alpha-0.1 -t http://example.com/archive/<version>.zip

Usage: niv add PACKAGE [-n|--name NAME] 
                 [(-a|--attribute KEY=VAL) | (-s|--string-attribute KEY=VAL) | 
                   (-b|--branch BRANCH) | (-o|--owner OWNER) | (-r|--rev REV) | 
                   (-v|--version VERSION) | (-t|--template URL) | 
                   (-T|--type TYPE)]

  Add a GitHub dependency

Available options:
  -n,--name NAME           Set the package name to <NAME>
  -a,--attribute KEY=VAL   Set the package spec attribute <KEY> to <VAL>, where
                           <VAL> may be JSON.
  -s,--string-attribute KEY=VAL
                           Set the package spec attribute <KEY> to <VAL>.
  -b,--branch BRANCH       Equivalent to --attribute branch=<BRANCH>
  -o,--owner OWNER         Equivalent to --attribute owner=<OWNER>
  -r,--rev REV             Equivalent to --attribute rev=<REV>
  -v,--version VERSION     Equivalent to --attribute version=<VERSION>
  -t,--template URL        Used during 'update' when building URL. Occurrences
                           of <foo> are replaced with attribute 'foo'.
  -T,--type TYPE           The type of the URL target. The value can be either
                           'file' or 'tarball'. If not set, the value is
                           inferred from the suffix of the URL.
  -h,--help                Show this help text

Experimental commands:
  git                      Add a git dependency. Experimental.
  github                   Add a GitHub dependency
  local                    Add a local dependency. Experimental.

Update

Examples:
  
  niv update                     # update all packages
  niv update nixpkgs             # update nixpkgs
  niv update my-package -v beta-0.2 # update my-package to version "beta-0.2"

Usage: niv update [PACKAGE 
                    [(-a|--attribute KEY=VAL) | 
                      (-s|--string-attribute KEY=VAL) | (-b|--branch BRANCH) | 
                      (-o|--owner OWNER) | (-r|--rev REV) | 
                      (-v|--version VERSION) | (-t|--template URL) | 
                      (-T|--type TYPE)]]

  Update dependencies

Available options:
  -a,--attribute KEY=VAL   Set the package spec attribute <KEY> to <VAL>, where
                           <VAL> may be JSON.
  -s,--string-attribute KEY=VAL
                           Set the package spec attribute <KEY> to <VAL>.
  -b,--branch BRANCH       Equivalent to --attribute branch=<BRANCH>
  -o,--owner OWNER         Equivalent to --attribute owner=<OWNER>
  -r,--rev REV             Equivalent to --attribute rev=<REV>
  -v,--version VERSION     Equivalent to --attribute version=<VERSION>
  -t,--template URL        Used during 'update' when building URL. Occurrences
                           of <foo> are replaced with attribute 'foo'.
  -T,--type TYPE           The type of the URL target. The value can be either
                           'file' or 'tarball'. If not set, the value is
                           inferred from the suffix of the URL.
  -h,--help                Show this help text

Modify

Examples:

  niv modify nixpkgs -v beta-0.2
  niv modify nixpkgs -a branch=nixpkgs-unstable

Usage: niv modify PACKAGE [-n|--name NAME] 
                  [(-a|--attribute KEY=VAL) | (-s|--string-attribute KEY=VAL) | 
                    (-b|--branch BRANCH) | (-o|--owner OWNER) | (-r|--rev REV) |
                    (-v|--version VERSION) | (-t|--template URL) | 
                    (-T|--type TYPE)]

  Modify dependency attributes without performing an update

Available options:
  -n,--name NAME           Set the package name to <NAME>
  -a,--attribute KEY=VAL   Set the package spec attribute <KEY> to <VAL>, where
                           <VAL> may be JSON.
  -s,--string-attribute KEY=VAL
                           Set the package spec attribute <KEY> to <VAL>.
  -b,--branch BRANCH       Equivalent to --attribute branch=<BRANCH>
  -o,--owner OWNER         Equivalent to --attribute owner=<OWNER>
  -r,--rev REV             Equivalent to --attribute rev=<REV>
  -v,--version VERSION     Equivalent to --attribute version=<VERSION>
  -t,--template URL        Used during 'update' when building URL. Occurrences
                           of <foo> are replaced with attribute 'foo'.
  -T,--type TYPE           The type of the URL target. The value can be either
                           'file' or 'tarball'. If not set, the value is
                           inferred from the suffix of the URL.
  -h,--help                Show this help text

Drop

Examples:

  niv drop jq
  niv drop my-package version

Usage: niv drop PACKAGE [ATTRIBUTE]

  Drop dependency

Available options:
  -h,--help                Show this help text

Init

Usage: niv init [--fast | --latest | --nixpkgs OWNER/REPO
                  (-b|--nixpkgs-branch ARG) |
                  --no-nixpkgs]

  Initialize a Nix project. Existing files won't be modified.

Available options:
  --fast                   Use the latest nixpkgs cached at
                           'https://github.com/nmattia/niv/blob/master/data/nixpkgs.json'.
                           This is the default.
  --latest                 Pull the latest unstable nixpkgs from NixOS/nixpkgs.
  --nixpkgs OWNER/REPO     Use a custom nixpkgs repository from GitHub.
  -b,--nixpkgs-branch ARG  The nixpkgs branch when using --nixpkgs ....
  --no-nixpkgs             Don't add a nixpkgs entry to sources.json.
  -h,--help                Show this help text

show

Usage: niv show [PACKAGE]

Available options:
  -h,--help                Show this help text

Frequently Asked Questions

Can I use private GitHub repositories?

Yes. There are two ways:

1. Use the git protocol

When using the git protocol, your public SSH keypair is used to authenticate you:

$ niv add git [email protected]:my_user/my_private_repo
2. Use the netrc file

in order to niv add a private github repo you'll need to:

  1. create a .netrc file with the following content
machine github.com
  login YOUR_GITHUB_USER_NAME
  password YOUR_GITHUB_TOKEN
  1. add the path to the above file to /etc/nix/nix.conf:
netrc-file = /PATH/TO/.netrc
  1. set GITHUB_TOKEN env var when calling niv add
GITHUB_TOKEN=$YOUR_GITHUB_TOKEN niv add ...

How do I import and use the content of a source?

The way to import a source depend mainly on the content targetted by this source. A source could be a file, a repository with no knowledge of nix or a repository already in the nix ecosystem.

1. Direct import of a nix based source

In the case of a nix based source, you'll often find a default.nix at the root. Let's take this repository as example. We can add it to our sources.json with the following command.

$ niv add nmattia/niv

We can now import niv to use it a nix expression, e.g.:

{ sources ? import nix/sources.nix }:
let niv = import sources.niv {};
in { inherit niv; } # A glorious expression using the reference to niv

2. Import of a nix based source via an overlay

Rather than use the resulting derivation directly, you can add it to your custom nixpkgs via the overlay system.

{ sources ? import nix/sources.nix}:
let overlay = _: pkgs: {
      niv = (import sources.niv {}).niv;
    };
    nixpkgs = import sources.nixpkgs { overlays = [ overlay ]; config = {}; };
in { inherit (nixpkgs) niv; } # A glorious expression where nixpkgs.niv is referenced

3. Reference to the source's files in the nix store

You can also reference a simple file, a folder or a repo without nix knowledge with niv. In these cases, you can use the source in your nix expression without importing it.

The following exemple will compile gnu hello while using this technique to retrieve the source. First, we need to add the new source.

$ niv add hello-src -v 2.10 -t 'https://ftp.gnu.org/gnu/hello/hello-<version>.tar.gz'

Then, we can use it inside a nix expression.

{ sources ? import nix/sources.nix }:
let hello_src = sources.hello-src;
    nixpkgs =  import sources.nixpkgs {};
in nixpkgs.stdenv.mkDerivation {
    pname = "hello";
    version = "custom";
    src = hello_src;
}

⚠️ If you have problems, consider using the outPath of the source (e.g. sources.hello-src.outPath) instead of the source directly. See this issue for more details.

How do I import a subpath of a source?

In order to use the directory dir of a my-package, use the following pattern:

let
  sources = import ./nix/sources.nix;
in sources.my-package + "/dir"

in this example, sources.my-package becomes my-package's root directory, and + "/dir" appends the subdirectory.

How do I import NixOS modules?

After the package containing the modules has been niv added, importing the modules is straightforward:

let
  sources = import ./nix/sources.nix;
in {
  imports = [ (sources.package + "/path/to/module") ];
}

Can I use local packages?

If you need to use a local path as a source -- especially convenient when modifying dependencies -- niv allows you to override the sources.json via environment variables. To override a source foo with a local path ./bar/baz, set the environment variable NIV_OVERRIDE_foo to ./bar/baz.

Generally, if the environment variable NIV_OVERRIDE_<name> is set and you have a source named <name> then niv will use the value of NIV_OVERRIDE_<name> as the outPath of that source. All non-alphanumeric characters in the source name are escaped to the character _; i.e. to override the package my package-foo you need to set the environment variable NIV_OVERRIDE_my_package_foo.

Can I use a git dependency with submodules?

Yes, however you need to follow some steps.

Add your dependency as git dependency to your sources.json:

niv add git [email protected]:user/repo -n name

Add "submodules": true, to your dependecy in the source.json:

{
    "name": {
        "branch": "main",
        "repo": "[email protected]:user/repo",
        "rev": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
        "submodules": true,
        "type": "git"
    }
}

niv's People

Contributors

athas avatar bb010g avatar brano543 avatar bsima avatar cprussin avatar dependabot[bot] avatar domenkozar avatar eyjhb avatar flandweber avatar jbgi avatar jtojnar avatar kampka avatar kfollesdal avatar knl avatar l0b0 avatar ldprg avatar leotaku avatar madjar avatar michaelpj avatar mweinelt avatar ncfavier avatar nlewo avatar nmattia avatar osa1 avatar refnil avatar sivizius avatar srhb avatar tfc avatar yorickvp avatar zimbatm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

niv's Issues

grouping / tagging of sources

I'd love to use niv for updating my VSCode extensions, but would hate to have to enter niv update [name] for each of them every single time.

ParseError "Error in $: key \"description\" not present"

Not sure what the error is, the repository does have a description.

$ niv add 99designs/gqlgen 
Reading sources file
WARNING: Could not read from GitHub repo: 99designs/gqlgen
I assumed that your package was a GitHub repository. An error occurred while
gathering information from the repository. Check whether your package was added
correctly:

  niv show

If not, try re-adding it:

  niv drop <package>
  niv add <package-without-typo>

Make sure the repository exists.

(Error was: ParseError "Error in $: key \"description\" not present" )

One or more packages failed to update:
gqlgen: ParseError "Error in $: key \"description\" not present"
CallStack (from HasCallStack):
  error, called at src/Niv/GitHub.hs:43:9 in niv-0.1.1-JA4AHhZ4RkBKIGCn3c0RWr:Niv.GitHub

Custom updater script

How would I use niv to update package, that requires custom update script?

For example

to update https://github.com/srghma/nixpkgs/blob/aadfa893ab25d2410590faff1e3fbbdd4d89b2e3/pkgs/applications/misc/hubstaff/default.nix

there is a script https://github.com/srghma/nixpkgs/blob/aadfa893ab25d2410590faff1e3fbbdd4d89b2e3/pkgs/applications/misc/hubstaff/update.sh

that finds last version of hubstaff package on s3 and makes file https://github.com/srghma/nixpkgs/blob/aadfa893ab25d2410590faff1e3fbbdd4d89b2e3/pkgs/applications/misc/hubstaff/revision.json that is then imported builtins.fromJSON (builtins.readFile ./revision.json);


How would one use niv for hubstaff?

Could niv configuration file store script that is needs to run in order to update?

Separate `update` and `modify` commands?

At the moment update handles both changing attributes and updating the rev from the upstream repository.

You might well want to do these separately, e.g. change the tracking branch but don't update right now.

Perhaps separate niv update and niv modify commands would make sense.

Add fetcher for fetchPypi

fetchPypi just calls fetchurl underneath but has a slightly different calling syntax in order to construct the URL. It would be great to track these external dependencies using niv. :-)

fetchGit and submodules

I love the support for 'normal' GitHub repo's, but niv in its current implementation can't include the submodules, which makes it useless in some cases.
This can be solved by adding support for fetchGit.

Concurrency and sexy logging

Right now niv updates packages one after the other. This can be slow if the nix/sources.json contains lots of packages.

There's a branch somewhere that simply calls (something similar to) forConcurrently when iterating over the packages to upgrade. The main drawback is that all outputs get mangled.

I recently played with an idea for a logger (I unfortunately lost the niv branch):

  • A single thread is responsible for rendering and has associated state. The state looks something like TVar (Map Key [String]) where each Key is allocated some screen space which can grow and shrink depending on the [String] (the lines to display). This is made possible by the use of ANSI control codes.
  • There is one Key issued per thread. Whenever the code calls (an overriden version of) putStrln, myThreadId is used to generate the Key. It then writes its new output to the global (TVar (Map Key [String])) rendering state.

Update packages with common attribute values

It would be nice to be able to update a set of dependency as a whole. For instance, update all Docker images with tag latest. Another example is currently implemented in the nixpkgs-tungsten repository https://github.com/cloudwatt/nixpkgs-tungsten/blob/master/tools/sources.sh: several repositories with identical branches have to be fetched to build the project. It’d be nice to be able to only update all identical branches (targeting the same release).

The idea is to add a match option on the update and drop commands. The match option takes a key value pair. The update command only updates dependencies matching the pair.
Usage example

niv update [<name>] [--match <KEY=VALUE>] [--attribute <KEY=VALUE>]

# To update all docker images with a tag latest
niv update --match type=docker --match tag=latest
niv update nixpkgs

Note this could also be useful for drop and show commands.

niv drop [<name>] [--match <KEY=VALUE>]
    
niv drop --match type=docker

Error during niv add

Hello,

I face this error when I don't provide the revision:

$ niv add terraform-providers/terraform-provider-vault                                                                       
Reading sources file
One or more packages failed to update:
terraform-provider-vault: No rev: ParseError "Error in $[24].committer: key \"id\" not present"
CallStack (from HasCallStack):
  error, called at src/Niv/GitHub.hs:136:19 in niv-0.1.1-JA4AHhZ4RkBKIGCn3c0RWr:Niv.GitHub

`niv verify` command to verify already tracked packages

Sometimes, the url of a package can disappear or the content can be updated in place (the sha is then no longer valid).
It would be nice to have a niv verify [PACKAGE] [--update-sha] command to verify the url and sha are still valid. The --update-sha option could be use to ask niv to update the sha if it differs.
Some tools call this kind of command fsck.

Present a diff of the update before writing it to file

I'd like to have niv produce a (git-like) diff of the PackageSpec before it's written to file. This could be a CLI opt like niv update --dry-run or niv update --give-choice.

Note: we're gonna run into some difficulties if #73 is implemented.

GitHub Enterprise and custom hostname support

It would be nice to support custom hostnames.

We already use something similar in the tests:

niv/tests/default.nix

Lines 24 to 27 in 5d9e3a5

prePatch = ''
sed "s|GH.executeRequest'|GH.executeRequest (GH.EnterpriseOAuth \"http://localhost:3333\" \"\")|" -i app/Niv.hs
sed "s|https://github.com|http://localhost:3333|" -i app/Niv.hs
'';

A few thoughts:

  • The hub command line tool uses the GITHUB_HOST environment variable. However in our case we'd probably want to store the hostname in the sources.json: it's not unlikely for someone to use a custom github deployment and also open source packages.
  • The github library seems to use the host name directly when communicating with the API. This seems to be at odds with the GitHub Enterprise documentation which stipulates that the API should be reached at http(s)://[hostname]/api/v3. We can't ask for [hostname]/api/v3 to be passed as GITHUB_HOST because we'll use the raw ([hostname]) hostname for creating the URL. CC @phadej
  • Unlike the GITHUB_HOST we do not want to store the GITHUB_TOKEN in the sources.json. Either we don't allow the user to use multiple tokens, or we ask the user to issue a niv update <package> for each package hosted on a custom GitHub deployment. Alternatively we go crazy and allow the user to either (1) map a specific environment variable per token (e.g. GITHUB_TOKEN_[PACKAGE]) or we (2) ask the user to specify a command in the sources.json which will return the token (e.g. pass my-github-token-for-package).

CC @nlewo

Command line attribute `rev` is ignored

The rev attribute is ignored when provided on CLI.

Considering niv add NixOS/nixpkgs -a rev=plop, the sources.json should contains rev=plop while rev have been updated according to the --branch attribute.

Specifying a rev attribute is useful when switching a project to Niv because it allows to introduce Niv without changing what is actually built.

Handle the case when revision is wrong/non-existant

When running the following:

niv update terraform-provider-github -a rev=v2.21.0

I got:

Update terraform-provider-github
  Reading sources file
Could not read the output of 'nix-prefetch-url'. This is a bug. Please create a
ticket:

  https://github.com/nmattia/niv/issues/new

Thanks! I'll buy you a beer.
stdout:

stderr:
error: unable to download 'https://github.com/terraform-providers/terraform-provider-github/archive/v2.21.0.tar.gz': HTTP error 404


One or more packages failed to update:
terraform-provider-github: ExitFailure 1

ERROR: ExitFailure 1

The problem is that v2.21.0 doesn't exist (I made a typo).

Niv bisect, niv diff, niv <some-op-on-source>

Similar to #69

Niv actually has access to a lot of information. It could compare new and old revs to provided changelog changes (#69 ), diff the sources, or even run some actions on all the revs between rev0 and rev1 (similar to git bisect).

Use the GitHub search API to allow `niv add niv`

The GitHub search api allows us to lookup projects by name. If a project has a unique name, it could then be added with niv add niv leaving aside the project owner's name (niv add nmattia/niv).

Infer user nixpkgs commit

The feature I miss at first is that the default pin isn't related to my NIX_PATH at all. It would be nice (for me) if the tool consulted NIX_PATH and set the pin from the commit my current nixpkgs checkout is at.

I'm not very familiar with NIX_PATH. Mine is set like this:

$ echo $NIX_PATH 
nixpkgs=https://api.github.com/repos/NixOS/nixpkgs-channels/tarball/168cbb39691cca2822ce1fdb3e8c0183af5c6d0d

but I'm guessing most people use channels and the like. Is there a list of the allowed formats, and what people usually have in there?

Not installing niv?

We've had a situation where two or more versions of niv were in use. They come from

  • Alice's profile (nix-env -i as recommended)
  • Bob's profile
  • the project (shell.nix)

Two first two will never be consistent, so it seems best to rely on the second, but that creates a problem with bootstrapping. So I figured that to run niv init without installing, I could run

nix run -f https://github.com/nmattia/niv/tarball/master niv -c niv init

So, is this a method that should be recommended?
If so, it would be nice to reintroduce a default shell.nix, optionally, so you'd have:

$ nix run -f https://github.com/nmattia/niv/tarball/master niv -c niv init --scaffold
$ nix-shell
[nix-shell]$ niv add foo/bar

license

I see license: MIT but there should be a file (or a header in each file).

New command “niv changelog”

It’d be ultra nice to display a diff of the changelog (CHANGELOG.md on GH) when updating a GitHub repo. Alternatively there could also be a niv changelog command that just displays the changes since the last rev.

niv can't be used to pin NixOS

When pinning NixOS by setting nixpkgs in the $NIX_PATH to a file that imports nixpkgs from sources.nix, an infinite recursion will be entered because niv believes it has nixpkgs available and tries to use fetchers from the nixpkgs version it is supposed to fetch.

Nicer niv show UX

Right now niv show just dumps a bunch of info. It'd be nice to have niv show <package> and niv show <package> <attributes...>.

Feature request: Only fetch from GitHub when rev is updated

niv update currently always downloads and unpacks the tarballs received from GitHub, even if the revision has not changed. For a project that has multiple larger dependencies, this can be very time-consuming. (especially since the tarballs are fetched 2 times, once for the initial update and once at the following build)

As Niv already has GitHub support in updating the rev and sha based on the branch property, maybe you would be willing to add a special case where the tarball is not refetched should the rev stay the same.

I personally think this would be a good improvement to the UX of Niv, but it might of course not fit with your vision for the project.

More graceful error when running `niv add` without `niv init`

A the moment you get:

Could not read nix/sources.nix
Error: nix/sources.nix: openBinaryFile: does not exist (No such file or directory)

Reading sources file
niv: nix/sources.json: openBinaryFile: does not exist (No such file or directory)

Or even better, we could create the files at this point.

Optional config.nix collocated with sources.nix

It occurred to me that we could have an optional config.nix file located at ./config.nix where ./. is the directory containing the sources.nix.

The configuration could specify which packages use builtin fetchers ( #46 ) and specify the relative location of the sources.json (#102 ).

Because sources.nix is the only file the user has to care about, the UX wouldn't be affected: the config.nix would live in the same directory, but sources.json could live anywhere. We can trivially implement this using pathExists to check whether config.nix exists or not, without breaking backwards compatibility.

Thoughts @michaelpj @nlewo @masaeedu ?

`niv init --bare`

The niv init currently creates a bit too many files for my liking. Currently niv init is playing two roles:

  • install the nix/source.{nix,json} files which are indispensable, need to be at that location and managed by niv.
  • populate the folder with some default files.

By separating those two it might be clearer what files niv really needs when it's generated.

The default generated files are also not quite to my personal preferences. My default template would be:

  • the nix/source.{nix,json} files
  • a shell.nix that loads source.nixpkgs
  • a .envrc with use nix

I can easily expand that later if needed.

So I propose:

  • niv init --bare only creates the bare-minimum files
  • some way to override the default template, maybe use the content of ~/.config/niv/template if it exists?

GitHub errors are not reported to the user anymore

All the user gets is this:

One or more packages failed to update:
niv: No rev: ParseError "Error in $: expected Vector a, encountered Object"
CallStack (from HasCallStack):
  error, called at src/Niv/GitHub.hs:136:19 in niv-0.1.1-JA4AHhZ4RkBKIGCn3c0RWr:Niv.GitHub

Probably a change to the github library.

Different folder for `niv init`

Might be a little late for this, but I'd prefer it if all my niv stuff went into .niv instead of nix. I was wondering if there's a way to make this configurable and still have everything work?

Source updates should record the change date

The convention for unstable packages is to use the last modification date as version. Niv should assist in setting this by recording it when updating in a property like date.

For VCS sources, this should be the date of the latest change (e.g. Git's commit date). For file sources, this can default to the current date. Datestamps should be normalized to UTC.

New update mechanism (#68) breaks conditional prefetch

I recently noticed that the new update mechanism implemented in #68 removes the "only prefetch when url has changed" functionality introduced in #24. I personally think that this feature is pretty useful, so maybe we could have it be reintroduced?

PS: I am currently assuming that the feature hasn't been implemented in the never version, rather than it just being bugged and not working. I couldn't see any code related to it when skimming the source, but maybe this is really a bug.

Convenience functions for lifting IO to Update

The run :: (a -> IO b) -> Update (Box a) (Box b) function takes any IO function and turns it into an update function. This quickly gets awkward when several parameters need to be passed:

...
      repoInfo <- run (\(a, b) -> ghRepo a b) -< (,) <$> owner <*> repo
...

(link)

It'd be much nicer to have

      repoInfo <- run2 ghRepo -< (owner,repo)

(and the equivalent run3, run4, etc) or a single run that accepts pretty much anything through typeclass magic.

Create default.nix during niv init

The niv init command used to create a few files (default.nix, shell.nix, etc) which some people didn't like. Some people now complain that they want it back. I think the best solution here is to have niv init create a single extra file, default.nix, which

  1. shows how to import nix/sources.nix
  2. builds a single (pkgs.hello) package,
  3. potentially create a shell if inNixShell

non-nix deployment workflow/toolchain

Hi @nmattia,

Your approach here reminded me of a maybe-out-of-scope problem I've been stewing on. Just hoping to air it out and get your thoughts. My notes are very context-specific, but I suspect this is a fairly general problem that manifests differently for various language/toolchain combinations.

Over the past ~year I've been moving from VMs to Nix development environments for more and more of my projects, but I've got a workflow issue with a Python project that has its dependencies installed via pip for both CI and in production. (CI uses requirements_dev.txt, production uses requirements_common.txt, both also call requirements_common.txt)

The initial generation of a working {shell,requirements}.nix to install the Python dependencies was a bit cumbersome, largely because it involved learning and specifying sub dependencies. It works well with the work invested, but I also feel like I'm sitting on a future maintenance chore. The pip requirements files specify ~35 packages, a handful of which are sub-dependencies that needed to be explicitly pinned at some point; requirements.nix specifies 77 packages and updates to any given package could either cause dependency drift or require manually plumbing the sub-dependency network for updates.

Ideally I could offload most of this dependency work on nixpkgs, but I'm a little daunted by the (perhaps incorrectly?) perceived complexity of maintaining reproducibility between packages from one or more nix channel and a list of mostly-version-pinned pip packages. Nix cuts a lot of small frictions out of my workflow, but one cost has been giving up a single authoritative list of dependencies.

I've made notes here and there about writing a few bash scripts to solve some acute issues. For example, I could address single source-of-truth on dependencies by installing pip and adding a script step to the shell.nix that uses pip to export the list of nix-installed Python packages, filters out everything that doesn't match a list, and plugs them back into a requirements.txt template. But, these also feel like very small/local fixes to frictions that I assume others also experience...

  1. I've felt for a few months like either I or the Nix ecosystem may be missing some combination of generic/language-specific tools for bi-directional dependency workflows. I'm curious what you think about the problem generally, especially if you think I'm overlooking or overthinking some things.

  2. It looks like niv is working on the "inbound" direction in a generic way that made me think it might be well-positioned as a nexus for building up smaller language/ecosystem-specific tools. If so, it might vastly simplify their work/scope and make it more likely that the whole Nix ecosystem can benefit from robust tools for many languages. Inbound tools (analogs of the many x2nix efforts) could handle importing packages from various ecosystem-idiomatic formats and hand them off to niv. Outbound tools (which might or might not be bundled with the inbound tools) could handle writing the same.

Some error cases silently do nothing

In particular, there are a number of cases where we expect a JSON object to be of a particular type, and if isn't we do nothing - we should probably fail noisily instead.

niv local <pkg> [--path /path/to/file]

I'd like to implement a simple way to switch between GitHub packages and local checkouts. Ideally it'd be as simple as:

$ niv local my-package

which would toggle between local checkout and upstream URL. I think the nicest would be for niv to check out the repo (using the sources.json's owner and repo fields) in a temporary directory and printing out the path. If --path is set, use that path (and skip the checkout). Finally if local has ever be used on a package, just reuse the specified path.

@erictapen would this solve the issue you mentioned here #19 (comment) ?

re-remove dependency on nixpkgs

I have previously used niv to bootstrap systems that do not have the nixpkgs repository downloaded/setup as well as a replacement for the non-reproducible nix-channel. niv's newly added dependence on nixpkgs for its fetchers makes this impossible.

From what I understand we use the nixpkgs fetchers in order to please hydra, which needs a "real" derivation instead of one that is manually created.

However in #32 it is mentioned that hydra can also be pleased by simply adding the outPath key to the derivation record.

So maybe we can lose the dependence on nixpkgs again?

compare with nix-update-source?

Hello, I just found out about about niv through the latest NixOS weekly. I maintain nix-update-source. I figure it's worth figuring out where you might prefer one or the other? (and maybe sharing/stealing some ideas ;))

From a quick skim, I'd summarize the difference as: niv is a CLI for adding/managing dependencies explicitly, creating a couple of self-contained files (sources.nix + json) which fetch the deps.
nix-update-source is more of a template-based system for updating sources without repeating yourself when updating packages, creating either a JSON file per dependency (importable via an API in nixpkgs itself) or in a "zero runtime" mode which updates nix expressions inline.

Initial thoughts on bringing the two ideas closer together (if we want to) would be adding an init-like action to nix-update-source, and on the other hand adding support for storing templates in the generated source of niv (so you don't have to specify them on the command line each time).

I also maintain nix-pin which is vaguely related, but is more for development setup (easily building local versions of multiple packages).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.