about summary refs log tree commit diff
path: root/nixpkgs/pkgs/development/tools/yarn2nix-moretea/yarn2nix/lib
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/pkgs/development/tools/yarn2nix-moretea/yarn2nix/lib')
-rw-r--r--nixpkgs/pkgs/development/tools/yarn2nix-moretea/yarn2nix/lib/fixPkgAddMissingSha1.js66
-rw-r--r--nixpkgs/pkgs/development/tools/yarn2nix-moretea/yarn2nix/lib/generateNix.js124
-rw-r--r--nixpkgs/pkgs/development/tools/yarn2nix-moretea/yarn2nix/lib/mapObjIndexedReturnArray.js21
-rw-r--r--nixpkgs/pkgs/development/tools/yarn2nix-moretea/yarn2nix/lib/urlToName.js21
4 files changed, 232 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/development/tools/yarn2nix-moretea/yarn2nix/lib/fixPkgAddMissingSha1.js b/nixpkgs/pkgs/development/tools/yarn2nix-moretea/yarn2nix/lib/fixPkgAddMissingSha1.js
new file mode 100644
index 000000000000..2826f36e3260
--- /dev/null
+++ b/nixpkgs/pkgs/development/tools/yarn2nix-moretea/yarn2nix/lib/fixPkgAddMissingSha1.js
@@ -0,0 +1,66 @@
+const https = require('https')
+const crypto = require('crypto')
+
+// TODO:
+// make test case where getSha1 function is used, i.e. the case when resolved is without sha1?
+// consider using https://github.com/request/request-promise-native
+
+function getSha1(url) {
+  return new Promise((resolve, reject) => {
+    https.get(url, res => {
+      const { statusCode } = res
+      const hash = crypto.createHash('sha1')
+
+      if (statusCode !== 200) {
+        const err = new Error(`Request Failed.\nStatus Code: ${statusCode}`)
+
+        // consume response data to free up memory
+        res.resume()
+
+        reject(err)
+      }
+
+      res.on('data', chunk => {
+        hash.update(chunk)
+      })
+
+      res.on('end', () => {
+        resolve(hash.digest('hex'))
+      })
+
+      res.on('error', reject)
+    })
+  })
+}
+
+// Object -> Object
+async function fixPkgAddMissingSha1(pkg) {
+  // local dependency
+
+  if (!pkg.resolved) {
+    console.error(
+      `yarn2nix: can't find "resolved" field for package ${
+        pkg.nameWithVersion
+      }, you probably required it using "file:...", this feature is not supported, ignoring`,
+    )
+    return pkg
+  }
+
+  const [url, sha1] = pkg.resolved.split('#', 2)
+
+  if (sha1) {
+    return pkg
+  }
+
+  // if there is no sha1 in resolved url
+  // (this could happen if yarn.lock was generated by older version of yarn)
+  // - request it from registry by https and add it to pkg
+  const newSha1 = await getSha1(url)
+
+  return {
+    ...pkg,
+    resolved: `${url}#${newSha1}`,
+  }
+}
+
+module.exports = fixPkgAddMissingSha1
diff --git a/nixpkgs/pkgs/development/tools/yarn2nix-moretea/yarn2nix/lib/generateNix.js b/nixpkgs/pkgs/development/tools/yarn2nix-moretea/yarn2nix/lib/generateNix.js
new file mode 100644
index 000000000000..964eaf2555d1
--- /dev/null
+++ b/nixpkgs/pkgs/development/tools/yarn2nix-moretea/yarn2nix/lib/generateNix.js
@@ -0,0 +1,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
diff --git a/nixpkgs/pkgs/development/tools/yarn2nix-moretea/yarn2nix/lib/mapObjIndexedReturnArray.js b/nixpkgs/pkgs/development/tools/yarn2nix-moretea/yarn2nix/lib/mapObjIndexedReturnArray.js
new file mode 100644
index 000000000000..83c6634f7c84
--- /dev/null
+++ b/nixpkgs/pkgs/development/tools/yarn2nix-moretea/yarn2nix/lib/mapObjIndexedReturnArray.js
@@ -0,0 +1,21 @@
+const _curry2 = require('ramda/src/internal/_curry2')
+const _map = require('ramda/src/internal/_map')
+const keys = require('ramda/src/keys')
+
+// mapObjIndexed: ((v, k, {k: v}) → v') → {k: v} → {k: v'}
+// mapObjIndexedReturnArray: ((v, k, {k: v}) → v') → {k: v} → [v']
+
+/*
+ * @example
+ *
+ *      const xyz = { x: 1, y: 2, z: 3 };
+ *      const prependKeyAndDouble = (num, key, obj) => key + (num * 2);
+ *
+ *      mapObjIndexedReturnArray(prependKeyAndDouble, xyz); //=> ['x2', 'y4', 'z6']
+ */
+
+const mapObjIndexedReturnArray = _curry2((fn, obj) =>
+  _map(key => fn(obj[key], key, obj), keys(obj)),
+)
+
+module.exports = mapObjIndexedReturnArray
diff --git a/nixpkgs/pkgs/development/tools/yarn2nix-moretea/yarn2nix/lib/urlToName.js b/nixpkgs/pkgs/development/tools/yarn2nix-moretea/yarn2nix/lib/urlToName.js
new file mode 100644
index 000000000000..81feaaf3a659
--- /dev/null
+++ b/nixpkgs/pkgs/development/tools/yarn2nix-moretea/yarn2nix/lib/urlToName.js
@@ -0,0 +1,21 @@
+const path = require('path')
+
+// String -> String
+
+// @url examples:
+// - https://registry.yarnpkg.com/acorn-es7-plugin/-/acorn-es7-plugin-1.1.7.tgz
+// - https://registry.npmjs.org/acorn-es7-plugin/-/acorn-es7-plugin-1.1.7.tgz
+// - git+https://github.com/srghma/node-shell-quote.git
+// - git+https://1234user:1234pass@git.graphile.com/git/users/1234user/postgraphile-supporter.git
+
+function urlToName(url) {
+  if (url.startsWith('git+')) {
+    return path.basename(url)
+  }
+
+  return url
+    .replace('https://registry.yarnpkg.com/', '') // prevents having long directory names
+    .replace(/[@/:-]/g, '_') // replace @ and : and - characters with underscore
+}
+
+module.exports = urlToName