Skip to content

Instantly share code, notes, and snippets.

@toraritte
Last active July 27, 2022 02:40
Show Gist options
  • Save toraritte/a69f71d169e8f163103d70c392f26d8a to your computer and use it in GitHub Desktop.
Save toraritte/a69f71d169e8f163103d70c392f26d8a to your computer and use it in GitHub Desktop.

Fetch a Git repo.

Types

  referenceToGitRepo = URL | path | gitArgs

  URL = httpURL | httpsURL | ftpURL | fileURL

  httpURL = string
    Needs to conform to the http:// URI scheme (see RFC 9110, section 4.2).

  httpsURL = string
    Needs to conform to the https:// URI scheme (see RFC 9110, section 4.2).

  ftpURL = string
    Needs to conform to the ftp:// URI scheme (see RFC 1738, section 3.2).

fileURL = "file://" + fileURLPathPart
fileURLPathPart = string
  Both need to conform to the file:// URI scheme (see the path syntax of RFC 8089).

path = Nix path | fileURLPathPart


gitArgs :: attribute set =
  { url :: (URL | path);
    [ name :: string ? "source" ];
    [ ref :: gitReferences ? "HEAD" ];
    [ rev :: gitFullCommitHash ? ? ];
    [ submodules :: boolean ? false ];
    [ shallow :: boolean ? false ];
    [ allRef :: boolean ? ? ];
  }

gitReferences = string
  Needs to be valid Git reference.

gitFullCommitHash = string
  Has to be full SHA-1 (for now object name (40-byte hexadecimal string) that refers to an existing commit in the repo.

storeResult :: attribute set = { lastModified lastModifiedDate narHash outPath rev revCount shortRev submodules}


Calling with a path

Example arguments:

  • Nix path: ~/clones/nix

  • fileURL: "file:///home/a_user/clones/nix"

  • fileURLPathPart: "/home/a_user/clones/nix"
    (This string will be prefixed with "file://", and then evaluated as a fileURL.)

  • gitArgs:

    • { url = ~/clones/nix; }
    • { url = "/home/a_user/clones/nix"; }
    • { url = "file:///home/a_user/clones/nix"; }

If the fetched repo is

  • "dirty"
    all uncommitted and/or unstaged changes will also be copied to the Nix store. storeResult's rev, shortRev, and revCount attributes will be all zeroes (as there is no commit associated with these changes yet).

    TIP
    To ignore changes when fetching a "dirty" repo, make sure to call gitArgs with ref or rev (e.g., { url = ./.; ref = "main"; }.). See more below.

  • "clean"
    the latest commit (or HEAD) of the currently checked-out branch will be retrieved.

① The latest commit (or HEAD) of the repo's default branch (typically called main or master) will be fetched. For completeness' sake, the supported URL schemes are: file://, http://, https://, ftp://

[2]: This string will be evaluated by prepending "file://" first, hence conformity to RFC 8089 is required.

[3]: "The full SHA-1 object name (40-byte hexadecimal string)", but it may be subject to change.

④ The name part of the Nix store path (TODO: link to where this is explained) where the Git repo's content will be copied to.

  • ref (optional)
    The git ref to look for the requested revision under. This is often a branch or tag name. Defaults to HEAD.

    By default, the ref value is prefixed with refs/heads/. As of Nix 2.3.0 Nix will not prefix refs/heads/ if ref starts with refs/.

  • rev (optional)
    The Git revision to fetch.
    Default value: if the ref attribute (see above) is specified,

  • submodules (optional)
    A Boolean parameter that specifies whether submodules should be checked out. Defaults to false.

  • shallow (optional)
    A Boolean parameter that specifies whether fetching a shallow clone is allowed. Defaults to false.

  • allRefs (optional)
    Whether to fetch all refs of the repository. With this argument being true, it's possible to load a rev from any ref (by default only revs from the specified ref are supported).

Here are some examples of how to use fetchGit.

  • To fetch a private repository over SSH:

    builtins.fetchGit {
      url = "[email protected]:my-secret/repository.git";
      ref = "master";
      rev = "adab8b916a45068c044658c4158d81878f9ed1c3";
    }
  • To fetch an arbitrary reference:

    builtins.fetchGit {
      url = "https://github.com/NixOS/nix.git";
      ref = "refs/heads/0.5-release";
    }
  • If the revision you're looking for is in the default branch of the git repository you don't strictly need to specify the branch name in the ref attribute.

    However, if the revision you're looking for is in a future branch for the non-default branch you will need to specify the the ref attribute as well.

    builtins.fetchGit {
      url = "https://github.com/nixos/nix.git";
      rev = "841fcbd04755c7a2865c51c1e2d3b045976b7452";
      ref = "1.11-maintenance";
    }

    Note

    It is nice to always specify the branch which a revision belongs to. Without the branch being specified, the fetcher might fail if the default branch changes. Additionally, it can be confusing to try a commit from a non-default branch and see the fetch fail. If the branch is specified the fault is much more obvious.

  • If the revision you're looking for is in the default branch of the git repository you may omit the ref attribute.

    builtins.fetchGit {
      url = "https://github.com/nixos/nix.git";
      rev = "841fcbd04755c7a2865c51c1e2d3b045976b7452";
    }
  • To fetch a specific tag:

    builtins.fetchGit {
      url = "https://github.com/nixos/nix.git";
      ref = "refs/tags/1.9";
    }
  • To fetch the latest version of a remote branch:

    builtins.fetchGit {
      url = "ssh://[email protected]/nixos/nix.git";
      ref = "master";
    }

    Note

    Nix will refetch the branch in accordance with the option tarball-ttl.

    Note

    This behavior is disabled in Pure evaluation mode.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment