summary refs log tree commit diff
path: root/pkgs/development/tools/yarn2nix-moretea/yarn2nix/lib/generateNix.js
blob: 964eaf2555d153c67f3fea433ca8451d3b670f81 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
const R = require('ramda')

const urlToName = require('./urlToName')
const { execFileSync } = require('child_process')

// fetchgit transforms
//
// "shell-quote@git+https://github.com/srghma/node-shell-quote.git#without_unlicenced_jsonify":
//   version "1.6.0"
//   resolved "git+https://github.com/srghma/node-shell-quote.git#1234commit"
//
// to
//
// builtins.fetchGit {
//   url = "https://github.com/srghma/node-shell-quote.git";
//   ref = "without_unlicenced_jsonify";
//   rev = "1234commit";
// }
//
// and transforms
//
// "@graphile/plugin-supporter@git+https://1234user:1234pass@git.graphile.com/git/users/1234user/postgraphile-supporter.git":
//   version "0.6.0"
//   resolved "git+https://1234user:1234pass@git.graphile.com/git/users/1234user/postgraphile-supporter.git#1234commit"
//
// to
//
// builtins.fetchGit {
//   url = "https://1234user:1234pass@git.graphile.com/git/users/1234user/postgraphile-supporter.git";
//   ref = "master";
//   rev = "1234commit";
// }

function prefetchgit(url, rev) {
  return JSON.parse(
    execFileSync("nix-prefetch-git", ["--rev", rev, url], {
      stdio: [ "ignore", "pipe", "ignore" ],
      timeout: 60000,
    })
  ).sha256
}

function fetchgit(fileName, url, rev, branch, builtinFetchGit) {
  return `    {
    name = "${fileName}";
    path =
      let${builtinFetchGit ? `
        repo = builtins.fetchGit {
          url = "${url}";
          ref = "${branch}";
          rev = "${rev}";
        };
      ` : `
        repo = fetchgit {
          url = "${url}";
          rev = "${rev}";
          sha256 = "${prefetchgit(url, rev)}";
        };
      `}in
        runCommandNoCC "${fileName}" { buildInputs = [gnutar]; } ''
          # Set u+w because tar-fs can't unpack archives with read-only dirs
          # https://github.com/mafintosh/tar-fs/issues/79
          tar cf $out --mode u+w -C \${repo} .
        '';
  }`
}

function fetchLockedDep(builtinFetchGit) {
  return function (pkg) {
    const { nameWithVersion, resolved } = pkg

    if (!resolved) {
      console.error(
        `yarn2nix: can't find "resolved" field for package ${nameWithVersion}, you probably required it using "file:...", this feature is not supported, ignoring`,
      )
      return ''
    }

    const [url, sha1OrRev] = resolved.split('#')

    const fileName = urlToName(url)

    if (url.startsWith('git+')) {
      const rev = sha1OrRev

      const [_, branch] = nameWithVersion.split('#')

      const urlForGit = url.replace(/^git\+/, '')

      return fetchgit(fileName, urlForGit, rev, branch || 'master', builtinFetchGit)
    }

    const sha = sha1OrRev

    return `    {
      name = "${fileName}";
      path = fetchurl {
        name = "${fileName}";
        url  = "${url}";
        sha1 = "${sha}";
      };
    }`
  }
}

const HEAD = `
{ fetchurl, fetchgit, linkFarm, runCommandNoCC, gnutar }: rec {
  offline_cache = linkFarm "offline" packages;
  packages = [
`.trim()

// Object -> String
function generateNix(pkgs, builtinFetchGit) {
  const nameWithVersionAndPackageNix = R.map(fetchLockedDep(builtinFetchGit), pkgs)

  const packagesDefinition = R.join(
    '\n',
    R.values(nameWithVersionAndPackageNix),
  )

  return R.join('\n', [HEAD, packagesDefinition, '  ];', '}'])
}

module.exports = generateNix