diff --git a/lib/datasource/cargo/index.js b/lib/datasource/cargo/index.js
index cf8f17e28995eae32acd85b68fbf4bde8feb6874..7b0a99b671f7ee6d82c861c5ad4f9580dbf26664 100644
--- a/lib/datasource/cargo/index.js
+++ b/lib/datasource/cargo/index.js
@@ -4,15 +4,14 @@ module.exports = {
   getPkgReleases,
 };
 
-async function getPkgReleases(purl) {
-  const { lookupName: name } = purl;
-  const crateUrl = `https://crates.io/api/v1/crates/${name}`;
+async function getPkgReleases({ lookupName }) {
+  const crateUrl = `https://crates.io/api/v1/crates/${lookupName}`;
   try {
     const res = (await got(crateUrl, {
       json: true,
     })).body;
     if (!(res && res.crate && res.crate.name)) {
-      logger.warn({ dependency: name }, `Received invalid crate data`);
+      logger.warn({ lookupName }, `Received invalid crate data`);
       return null;
     }
     const result = {
@@ -28,7 +27,7 @@ async function getPkgReleases(purl) {
     return result;
   } catch (err) {
     if (err.statusCode === 404 || err.code === 'ENOTFOUND') {
-      logger.info({ dependency: name }, `Dependency lookup failure: not found`);
+      logger.info({ lookupName }, `Dependency lookup failure: not found`);
       logger.debug(
         {
           err,
@@ -41,14 +40,11 @@ async function getPkgReleases(purl) {
       err.statusCode === 429 ||
       (err.statusCode > 500 && err.statusCode < 600)
     ) {
-      logger.warn(
-        { dependency: name, err },
-        `cargo crates.io registry failure`
-      );
+      logger.warn({ lookupName, err }, `cargo crates.io registry failure`);
       throw new Error('registry-failure');
     }
     logger.warn(
-      { err, dependency: name },
+      { err, lookupName },
       'cargo crates.io lookup failure: Unknown error'
     );
     return null;
diff --git a/lib/datasource/docker/index.js b/lib/datasource/docker/index.js
index 4cd7439e3400f3985960df691fabf5077df53d30..564a826d53a7815fcf80247213ff71b22f003c00 100644
--- a/lib/datasource/docker/index.js
+++ b/lib/datasource/docker/index.js
@@ -205,9 +205,11 @@ async function getManifestResponse(registry, repository, tag) {
  *  - Return the digest as a string
  */
 
-async function getDigest(config, newValue) {
-  const { registryUrls, depName } = config;
-  const { registry, repository } = getRegistryRepository(depName, registryUrls);
+async function getDigest({ registryUrls, lookupName }, newValue) {
+  const { registry, repository } = getRegistryRepository(
+    lookupName,
+    registryUrls
+  );
   logger.debug(`getDigest(${registry}, ${repository}, ${newValue})`);
   const newTag = newValue || 'latest';
   try {
@@ -238,7 +240,7 @@ async function getDigest(config, newValue) {
     logger.info(
       {
         err,
-        depName,
+        lookupName,
         newTag,
       },
       'Unknown Error looking up docker image digest'
@@ -337,10 +339,10 @@ async function getTags(registry, repository) {
  * This function will filter only tags that contain a semver version
  */
 
-async function getPkgReleases(purl, config = {}) {
+async function getPkgReleases({ lookupName, registryUrls }) {
   const { registry, repository } = getRegistryRepository(
-    purl.lookupName,
-    config.registryUrls
+    lookupName,
+    registryUrls
   );
   const tags = await getTags(registry, repository);
   if (!tags) {
diff --git a/lib/datasource/github/index.js b/lib/datasource/github/index.js
index 63141067bf8a7d6add6b08320b16d662e7a2861f..863712418884e4759f591f07504bac46c9079fc8 100644
--- a/lib/datasource/github/index.js
+++ b/lib/datasource/github/index.js
@@ -42,11 +42,7 @@ function getCacheKey(repo, type) {
  * This function will simply return the latest commit hash for the configured repository.
  */
 
-async function getDigest(config) {
-  let githubRepo = config.githubRepo || config.depNameShort;
-  if (!githubRepo && config.purl) {
-    githubRepo = config.purl.replace('pkg:github/', '').split('?')[0];
-  }
+async function getDigest({ lookupName: githubRepo }) {
   const cachedResult = await renovateCache.get(
     cacheNamespace,
     getCacheKey(githubRepo, 'commit')
@@ -89,13 +85,11 @@ async function getDigest(config) {
  *  - Return a dependency object containing sourceUrl string and releases array
  */
 
-async function getPkgReleases(purl) {
-  const { lookupName: repo } = purl;
-  const lookupType = purl.lookupType || 'tags';
+async function getPkgReleases({ lookupName: repo, lookupType }) {
   let versions;
   const cachedResult = await renovateCache.get(
     cacheNamespace,
-    getCacheKey(repo, lookupType)
+    getCacheKey(repo, lookupType || 'tags')
   );
   // istanbul ignore if
   if (cachedResult) {
diff --git a/lib/datasource/go/index.js b/lib/datasource/go/index.js
index 3eaf0d3598059612a0a7b47ff0dd4fd3f734f0c6..a6f3202b523c8c1ac4f04f621fe739e52f4250ba 100644
--- a/lib/datasource/go/index.js
+++ b/lib/datasource/go/index.js
@@ -1,28 +1,24 @@
 const got = require('../../util/got');
 const github = require('../github');
-const { parse } = require('../../util/purl');
 
 module.exports = {
   getPkgReleases,
   getDigest,
 };
 
-function getGithubPurl(repo) {
-  return {
-    lookupName: repo.replace(/\/$/, ''),
-  };
-}
-
-async function getSourcePurl(name) {
+async function getDatasource(name) {
   if (name.startsWith('gopkg.in/')) {
     const [pkg] = name.replace('gopkg.in/', '').split('.');
     if (pkg.includes('/')) {
-      return getGithubPurl(pkg);
+      return { datasource: 'github', lookupName: pkg };
     }
-    return getGithubPurl(`go-${pkg}/${pkg}`);
+    return { datasource: 'github', lookupName: `go-${pkg}/${pkg}` };
   }
   if (name.startsWith('github.com/')) {
-    return getGithubPurl(name.replace('github.com/', ''));
+    return {
+      datasource: 'github',
+      lookupName: name.replace('github.com/', ''),
+    };
   }
   const pkgUrl = `https://${name}?go-get=1`;
   try {
@@ -36,7 +32,12 @@ async function getSourcePurl(name) {
       const [, goSourceUrl] = sourceMatch;
       logger.debug({ depName: name, goSourceUrl }, 'Go lookup source url');
       if (goSourceUrl && goSourceUrl.startsWith('https://github.com/')) {
-        return getGithubPurl(goSourceUrl.replace('https://github.com/', ''));
+        return {
+          datasource: 'github',
+          lookupName: goSourceUrl
+            .replace('https://github.com/', '')
+            .replace(/\/$/, ''),
+        };
       }
     } else {
       logger.trace({ depName: name }, 'No go-source header found');
@@ -66,18 +67,17 @@ async function getSourcePurl(name) {
  *  - Call the respective getPkgReleases in github to retrieve the tags
  */
 
-async function getPkgReleases(purl) {
-  const { lookupName: name } = purl;
-  logger.trace(`go.getPkgReleases(${name})`);
-  const githubPurl = await getSourcePurl(name);
-  if (githubPurl) {
-    const githubTags = await github.getPkgReleases(githubPurl);
-    if (githubTags && githubTags.releases) {
-      githubTags.releases = githubTags.releases.filter(
+async function getPkgReleases({ lookupName }) {
+  logger.trace(`go.getPkgReleases(${lookupName})`);
+  const source = await getDatasource(lookupName);
+  if (source && source.datasource === 'github') {
+    const res = await github.getPkgReleases(source);
+    if (res && res.releases) {
+      res.releases = res.releases.filter(
         release => release.version && release.version.startsWith('v')
       );
     }
-    return githubTags;
+    return res;
   }
   return null;
 }
@@ -93,13 +93,10 @@ async function getPkgReleases(purl) {
  *  - Call the respective getDigest in github to retrieve the commit hash
  */
 
-async function getDigest(config) {
-  const purl = parse(config.purl);
-  const name = purl ? purl.lookupName : config.depName;
-  const githubPurl = await getSourcePurl(name);
-  if (githubPurl) {
-    const githubRepo = githubPurl.lookupName;
-    const digest = await github.getDigest({ ...config, githubRepo });
+async function getDigest({ lookupName }) {
+  const source = await getDatasource(lookupName);
+  if (source && source.datasource === 'github') {
+    const digest = await github.getDigest(source);
     return digest;
   }
   return null;
diff --git a/lib/datasource/index.js b/lib/datasource/index.js
index ced1e747dba89361394fa245030571915817cb93..f6942bd0215a4ac4a9d5e6b22fe7eac153a4fcbc 100644
--- a/lib/datasource/index.js
+++ b/lib/datasource/index.js
@@ -1,5 +1,4 @@
 const { addMetaData } = require('./metadata');
-const { parse } = require('../util/purl');
 const versioning = require('../versioning');
 
 const cargo = require('./cargo');
@@ -39,7 +38,10 @@ const datasources = {
 const cacheNamespace = 'datasource-releases';
 
 async function getPkgReleases(config) {
-  const res = await getRawReleases(config);
+  const res = await getRawReleases({
+    ...config,
+    lookupName: config.lookupName || config.depName,
+  });
   if (!res) {
     return res;
   }
@@ -60,7 +62,11 @@ async function getPkgReleases(config) {
 }
 
 function getRawReleases(config) {
-  const cacheKey = cacheNamespace + config.purl;
+  const cacheKey =
+    cacheNamespace +
+    config.datasource +
+    config.lookupName +
+    config.registryUrls;
   // The repoCache is initialized for each repo
   // By returning a Promise and reusing it, we should only fetch each package at most once
   if (!global.repoCache[cacheKey]) {
@@ -70,29 +76,30 @@ function getRawReleases(config) {
 }
 
 async function fetchReleases(config) {
-  const purlStr = config.purl;
-  const purl = parse(purlStr);
-  if (!purl) {
-    logger.info({ purlStr }, 'Cannot parse purl');
-    return null;
+  const { datasource } = config;
+  if (!datasource) {
+    logger.warn('No datasource found');
   }
-  if (!datasources[purl.datasource]) {
-    logger.warn({ purlStr }, 'Unknown purl type: ' + purl.datasource);
+  if (!datasources[datasource]) {
+    logger.warn('Unknown datasource: ' + datasource);
     return null;
   }
-  const dep = await datasources[purl.datasource].getPkgReleases(purl, config);
-  addMetaData(purl, dep);
+  const dep = await datasources[datasource].getPkgReleases(config);
+  addMetaData(dep, datasource, config.lookupName);
   return dep;
 }
 
-function supportsDigests(purlStr) {
-  const purl = parse(purlStr);
-  return !!datasources[purl.datasource].getDigest;
+function supportsDigests(config) {
+  return !!datasources[config.datasource].getDigest;
 }
 
 function getDigest(config, value) {
-  const purl = parse(config.purl);
-  return datasources[purl.datasource].getDigest(config, value);
+  const lookupName = config.lookupName || config.depName;
+  const { registryUrls } = config;
+  return datasources[config.datasource].getDigest(
+    { lookupName, registryUrls },
+    value
+  );
 }
 
 module.exports = {
diff --git a/lib/datasource/maven/index.js b/lib/datasource/maven/index.js
index 8e01a4805450b177e37c081216d66f31f501b9d2..c3bdff6df3d9ad3970b6dd4e9eec9573e862821a 100644
--- a/lib/datasource/maven/index.js
+++ b/lib/datasource/maven/index.js
@@ -11,14 +11,14 @@ module.exports = {
 };
 
 // eslint-disable-next-line no-unused-vars
-async function getPkgReleases(purl) {
+async function getPkgReleases({ lookupName, registryUrls }) {
   const versions = [];
-  const dependency = getDependencyParts(purl);
-  if (!is.nonEmptyArray(purl.registryUrls)) {
+  const dependency = getDependencyParts(lookupName);
+  if (!is.nonEmptyArray(registryUrls)) {
     logger.error(`No repositories defined for ${dependency.display}`);
     return null;
   }
-  const repositories = purl.registryUrls.map(repository =>
+  const repositories = registryUrls.map(repository =>
     repository.replace(/\/?$/, '/')
   );
   logger.debug(
@@ -68,13 +68,13 @@ async function getPkgReleases(purl) {
   };
 }
 
-function getDependencyParts(purl) {
-  const [group, name] = purl.lookupName.split('/');
+function getDependencyParts(lookupName) {
+  const [group, name] = lookupName.split('/');
   return {
-    display: purl.lookupName.replace('/', ':'),
+    display: lookupName.replace('/', ':'),
     group,
     name,
-    dependencyUrl: generateMavenUrl(purl),
+    dependencyUrl: generateMavenUrl(lookupName),
   };
 }
 
@@ -150,8 +150,8 @@ async function downloadHttpProtocol(pkgUrl) {
   return raw.body;
 }
 
-function generateMavenUrl(purl) {
-  const [group, name] = purl.lookupName.split('/');
+function generateMavenUrl(lookupName) {
+  const [group, name] = lookupName.split('/');
   return group.replace(/\./g, '/') + `/${name}`;
 }
 
diff --git a/lib/datasource/metadata.js b/lib/datasource/metadata.js
index 99d88ffa27993442cb66f5852ab89dacbd7d485e..30cee026e0e16f9cf17c1016d4b50f26bde441af 100644
--- a/lib/datasource/metadata.js
+++ b/lib/datasource/metadata.js
@@ -64,22 +64,19 @@ const manualSourceUrls = {
 };
 
 /* eslint-disable no-param-reassign */
-function addMetaData(purl, dep) {
+function addMetaData(dep, datasource, lookupName) {
   if (!dep) {
     return;
   }
-  const depName = purl.lookupName.toLowerCase();
+  const depName = lookupName ? lookupName.toLowerCase() : null;
   if (
-    manualChangelogUrls[purl.datasource] &&
-    manualChangelogUrls[purl.datasource][depName]
+    manualChangelogUrls[datasource] &&
+    manualChangelogUrls[datasource][depName]
   ) {
-    dep.changelogUrl = manualChangelogUrls[purl.datasource][depName];
+    dep.changelogUrl = manualChangelogUrls[datasource][depName];
   }
-  if (
-    manualSourceUrls[purl.datasource] &&
-    manualSourceUrls[purl.datasource][depName]
-  ) {
-    dep.sourceUrl = manualSourceUrls[purl.datasource][depName];
+  if (manualSourceUrls[datasource] && manualSourceUrls[datasource][depName]) {
+    dep.sourceUrl = manualSourceUrls[datasource][depName];
   }
   if (
     !dep.sourceUrl &&
diff --git a/lib/datasource/npm/releases.js b/lib/datasource/npm/releases.js
index 40fb221fe0eecafa1a7be662d4947aa90ed8ffd4..b340ac059c1c1b61f09a595a29550464e7a4b0d6 100644
--- a/lib/datasource/npm/releases.js
+++ b/lib/datasource/npm/releases.js
@@ -5,11 +5,11 @@ module.exports = {
   getPkgReleases,
 };
 
-async function getPkgReleases(purl, config) {
-  if (config && config.npmrc) {
-    setNpmrc(config.npmrc);
+async function getPkgReleases({ lookupName, npmrc }) {
+  if (npmrc) {
+    setNpmrc(npmrc);
   }
-  const res = await getDependency(purl.lookupName, global.testNpmRetries);
+  const res = await getDependency(lookupName, global.testNpmRetries);
   if (res) {
     res.tags = res['dist-tags'];
     delete res['dist-tags'];
diff --git a/lib/datasource/nuget/index.js b/lib/datasource/nuget/index.js
index 9e75cfe06503466e5b0b495894f111199ee8b27b..a7ce78dd3683c9b238dd274b7f531e092f2866d9 100644
--- a/lib/datasource/nuget/index.js
+++ b/lib/datasource/nuget/index.js
@@ -7,21 +7,20 @@ module.exports = {
   getPkgReleases,
 };
 
-async function getPkgReleases(purl) {
-  const { lookupName: name } = purl;
-  logger.trace(`nuget.getPkgReleases(${name})`);
-  const pkgUrl = `https://api.nuget.org/v3-flatcontainer/${name.toLowerCase()}/index.json`;
+async function getPkgReleases({ lookupName }) {
+  logger.trace(`nuget.getPkgReleases(${lookupName})`);
+  const pkgUrl = `https://api.nuget.org/v3-flatcontainer/${lookupName.toLowerCase()}/index.json`;
   try {
     const res = (await got(pkgUrl, {
       json: true,
       retry: 5,
     })).body;
     const dep = {
-      name,
+      name: lookupName,
     };
     dep.releases = (res.versions || []).map(version => ({ version }));
     // look up nuspec for latest release to get repository
-    const url = `https://api.nuget.org/v3-flatcontainer/${name.toLowerCase()}/${res.versions.pop()}/${name.toLowerCase()}.nuspec`;
+    const url = `https://api.nuget.org/v3-flatcontainer/${lookupName.toLowerCase()}/${res.versions.pop()}/${lookupName.toLowerCase()}.nuspec`;
     try {
       const result = await got(url);
       const nuspec = new XmlDocument(result.body);
@@ -34,19 +33,19 @@ async function getPkgReleases(purl) {
         }
       }
     } catch (err) /* istanbul ignore next */ {
-      logger.debug({ dependency: name }, 'Error looking up nuspec');
+      logger.debug({ lookupName }, 'Error looking up nuspec');
     }
     logger.trace({ dep }, 'dep');
     return dep;
   } catch (err) {
     if (err.statusCode === 404 || err.code === 'ENOTFOUND') {
-      logger.info({ dependency: name }, `Dependency lookup failure: not found`);
+      logger.info({ lookupName }, `Dependency lookup failure: not found`);
       logger.debug({
         err,
       });
       return null;
     }
-    logger.warn({ err, name }, 'nuget registry failure: Unknown error');
+    logger.warn({ err, lookupName }, 'nuget registry failure: Unknown error');
     return null;
   }
 }
diff --git a/lib/datasource/orb/index.js b/lib/datasource/orb/index.js
index 16bd9eb5527edd6873a7c39f53e475fc28affcb0..764490e4038fd91fa4142a56d2491b0607166399 100644
--- a/lib/datasource/orb/index.js
+++ b/lib/datasource/orb/index.js
@@ -10,11 +10,10 @@ module.exports = {
  * This function will fetch an orb from CircleCI and return all semver versions.
  */
 
-async function getPkgReleases(purl) {
-  const { lookupName: dependency } = purl;
-  logger.debug({ dependency }, 'orb.getPkgReleases()');
+async function getPkgReleases({ lookupName }) {
+  logger.debug({ lookupName }, 'orb.getPkgReleases()');
   const cacheNamespace = 'orb';
-  const cacheKey = dependency;
+  const cacheKey = lookupName;
   const cachedResult = await renovateCache.get(cacheNamespace, cacheKey);
   // istanbul ignore if
   if (cachedResult) {
@@ -22,7 +21,7 @@ async function getPkgReleases(purl) {
   }
   const url = 'https://circleci.com/graphql-unstable';
   const body = {
-    query: `{orb(name:"${dependency}"){name, homeUrl, versions {version, createdAt}}}`,
+    query: `{orb(name:"${lookupName}"){name, homeUrl, versions {version, createdAt}}}`,
     variables: {},
   };
   try {
@@ -33,14 +32,14 @@ async function getPkgReleases(purl) {
     })).body.data.orb;
     // Simplify response before caching and returning
     const dep = {
-      name: dependency,
+      name: lookupName,
       versions: {},
     };
     if (res.homeUrl && res.homeUrl.length) {
       dep.homepage = res.homeUrl;
     }
     dep.homepage =
-      dep.homepage || `https://circleci.com/orbs/registry/orb/${dependency}`;
+      dep.homepage || `https://circleci.com/orbs/registry/orb/${lookupName}`;
     dep.releases = res.versions.map(v => v.version);
     dep.releases = dep.releases.map(version => ({
       version,
@@ -51,14 +50,14 @@ async function getPkgReleases(purl) {
     return dep;
   } catch (err) /* istanbul ignore next */ {
     if (err.statusCode === 404 || err.code === 'ENOTFOUND') {
-      logger.info({ dependency }, `CircleCI Orb lookup failure: not found`);
+      logger.info({ lookupName }, `CircleCI Orb lookup failure: not found`);
       logger.debug({
         err,
       });
       return null;
     }
     logger.warn(
-      { err, dependency },
+      { err, lookupName },
       'CircleCI Orb lookup failure: Unknown error'
     );
     return null;
diff --git a/lib/datasource/packagist/index.js b/lib/datasource/packagist/index.js
index 9eefedb146ca41d94270ee1a1e302b50db1f7f6d..668e451d09f7b81d994cee0e50e8e3db58335dc7 100644
--- a/lib/datasource/packagist/index.js
+++ b/lib/datasource/packagist/index.js
@@ -244,10 +244,8 @@ async function packageLookup(regUrl, name) {
   }
 }
 
-async function getPkgReleases(purl, config = {}) {
-  const { lookupName: name } = purl;
-  const { registryUrls } = config;
-  logger.trace(`getPkgReleases(${name})`);
+async function getPkgReleases({ lookupName, registryUrls }) {
+  logger.trace(`getPkgReleases(${lookupName})`);
   const regUrls = [];
   if (registryUrls) {
     for (const regUrl of registryUrls) {
@@ -274,7 +272,7 @@ async function getPkgReleases(purl, config = {}) {
 
   let res;
   for (const regUrl of regUrls) {
-    res = await packageLookup(regUrl, name);
+    res = await packageLookup(regUrl, lookupName);
     if (res) {
       break;
     }
diff --git a/lib/datasource/pypi/index.js b/lib/datasource/pypi/index.js
index 1bbc050bb713c338c6e3b85d8999c06aef77efc4..dae36548a3bbc4ee57b9ebbf274b7a8a885bb066 100644
--- a/lib/datasource/pypi/index.js
+++ b/lib/datasource/pypi/index.js
@@ -27,18 +27,16 @@ function compatibleVersions(releases, compatibility) {
   );
 }
 
-async function getPkgReleases(purl, config = {}) {
-  const { compatibility } = config;
-  const { lookupName: depName } = purl;
+async function getPkgReleases({ compatibility, lookupName, registryUrls }) {
   let hostUrls = ['https://pypi.org/pypi/'];
-  if (is.nonEmptyArray(config.registryUrls)) {
-    hostUrls = config.registryUrls;
+  if (is.nonEmptyArray(registryUrls)) {
+    hostUrls = registryUrls;
   }
   if (process.env.PIP_INDEX_URL) {
     hostUrls = [process.env.PIP_INDEX_URL];
   }
   for (const hostUrl of hostUrls) {
-    const dep = await getDependency(depName, hostUrl, compatibility);
+    const dep = await getDependency(lookupName, hostUrl, compatibility);
     if (dep !== null) {
       return dep;
     }
diff --git a/lib/datasource/readme.md b/lib/datasource/readme.md
index adb34705e78eda9f8d6e7ee84c39738da4a3eea0..b585276252fb2dc6a101a5ac2d56ff033bfeee57 100644
--- a/lib/datasource/readme.md
+++ b/lib/datasource/readme.md
@@ -4,13 +4,13 @@ Datasources are used in Renovate primarily to fetch released versions of package
 
 ### getPkgReleases
 
-The minimum exported interface for a datasource is a function called `getPkgReleases` that takes a `purl` object as first input, and optionally `config` as the second argument.
+The minimum exported interface for a datasource is a function called `getPkgReleases` that takes a lookup config as input.
 
-The `purl` object contains:
+The config contains:
 
 - `lookupName`: the package's full name including scope if present (e.g. `@foo/bar`)
-
-In the simplest case, the datasource only needs to pay attention to `purl.lookupName`.
+- `lookupType`: used only when there is a need to specify different types of lookups within the same datasource
+- `registryUrls`: an array of registry Urls to try
 
 `getPkgReleases` should return an object containing:
 
@@ -27,7 +27,7 @@ Datasources that support the concept of digests (e.g. docker digests and git com
 
 The `getDigest` function has two inputs:
 
-- `config`: the Renovate config for the package being updated
+- `config`: the Renovate config for the package being updated, contains same fields as `getPkgReleases`
 - `newValue`: the version or value to retrieve the digest for
 
 The `getDigest` function returns a string output representing the digest value. If none is found then a return value of `null` should be returned.
diff --git a/lib/datasource/rubygems/releases.js b/lib/datasource/rubygems/releases.js
index e4f756edf4da10bf5f6cb894cb3f40d3cfb036b1..cb91619be3a57d0b223c8ae1d6b5257b02cb5366 100644
--- a/lib/datasource/rubygems/releases.js
+++ b/lib/datasource/rubygems/releases.js
@@ -1,12 +1,11 @@
 const { nonEmptyArray } = require('@sindresorhus/is');
 const { getDependency } = require('./get');
 
-async function getPkgReleases({ lookupName: dependency }, config = {}) {
-  const { registryUrls } = config;
+async function getPkgReleases({ lookupName, registryUrls }) {
   const registries = nonEmptyArray(registryUrls) ? registryUrls : [];
 
   for (const registry of registries) {
-    const pkg = await getDependency({ dependency, registry });
+    const pkg = await getDependency({ dependency: lookupName, registry });
     if (pkg) {
       return pkg;
     }
diff --git a/lib/datasource/terraform/index.js b/lib/datasource/terraform/index.js
index bb54b98914a3f824f6258ffdbab530a5787f2c09..aaa1410a74bf4fb2c5b1e8b16618fbe4af6918b7 100644
--- a/lib/datasource/terraform/index.js
+++ b/lib/datasource/terraform/index.js
@@ -36,10 +36,10 @@ function getRegistryRepository(lookupName, registryUrls) {
  *  - `homepage` is set to the Terraform registry's page if it's on the official main registry
  */
 
-async function getPkgReleases(purl, config) {
+async function getPkgReleases({ lookupName, registryUrls }) {
   const { registry, repository } = getRegistryRepository(
-    purl.lookupName,
-    config.registryUrls
+    lookupName,
+    registryUrls
   );
   logger.debug({ registry, repository }, 'terraform.getDependencies()');
   const cacheNamespace = 'terraform';
@@ -80,7 +80,7 @@ async function getPkgReleases(purl, config) {
   } catch (err) {
     if (err.statusCode === 404 || err.code === 'ENOTFOUND') {
       logger.info(
-        { dependency: purl.lookupName },
+        { lookupName },
         `Terraform registry lookup failure: not found`
       );
       logger.debug({
@@ -89,7 +89,7 @@ async function getPkgReleases(purl, config) {
       return null;
     }
     logger.warn(
-      { err, dependency: purl.lookupName },
+      { err, lookupName },
       'Terraform registry failure: Unknown error'
     );
     return null;
diff --git a/lib/manager/bazel/extract.js b/lib/manager/bazel/extract.js
index b4eaafc13b9438fb750da3aaa7b516763d3eab1f..1b839b5a303a98fb9ff0caa4f31dc12fdf239f08 100644
--- a/lib/manager/bazel/extract.js
+++ b/lib/manager/bazel/extract.js
@@ -90,7 +90,8 @@ function extractPackageFile(content) {
       dep.remote = remote;
       dep.currentValue = currentValue;
       const repo = parse(remote).substring('https://github.com/'.length);
-      dep.purl = 'pkg:github/' + repo;
+      dep.datasource = 'github';
+      dep.lookupName = repo;
       deps.push(dep);
     } else if (
       depType === 'go_repository' &&
@@ -100,13 +101,14 @@ function extractPackageFile(content) {
     ) {
       dep.depName = depName;
       dep.currentValue = currentValue || commit.substr(0, 7);
-      dep.purl = 'pkg:go/' + importpath;
+      dep.datasource = 'go';
+      dep.lookupName = importpath;
       if (remote) {
         const remoteMatch = remote.match(
           /https:\/\/github\.com(?:.*\/)(([a-zA-Z]+)([-])?([a-zA-Z]+))/
         );
         if (remoteMatch && remoteMatch[0].length === remote.length) {
-          dep.purl = 'pkg:go/' + remote.replace('https://', '');
+          dep.lookupName = remote.replace('https://', '');
         } else {
           dep.skipReason = 'unsupported-remote';
         }
@@ -128,7 +130,9 @@ function extractPackageFile(content) {
       dep.depName = depName;
       dep.repo = parsedUrl.repo;
       dep.currentValue = parsedUrl.currentValue;
-      dep.purl = 'pkg:github/' + dep.repo + '#releases';
+      dep.datasource = 'github';
+      dep.lookupName = dep.repo;
+      dep.lookupType = 'releases';
       deps.push(dep);
     } else {
       logger.info(
diff --git a/lib/manager/buildkite/extract.js b/lib/manager/buildkite/extract.js
index 63d0c813a19ed3d78d6878aa5d2750e11518bdab..2720623972f26a9ce6b17f981e033ffb456f734a 100644
--- a/lib/manager/buildkite/extract.js
+++ b/lib/manager/buildkite/extract.js
@@ -45,13 +45,17 @@ function extractPackageFile(content) {
               skipReason = 'unknown';
             }
           }
-          deps.push({
+          const dep = {
             lineNumber,
             depName,
-            purl: repo ? 'pkg:github/' + repo : undefined,
             currentValue,
             skipReason,
-          });
+          };
+          if (repo) {
+            dep.datasource = 'github';
+            dep.lookupName = repo;
+          }
+          deps.push(dep);
         }
       }
     }
diff --git a/lib/manager/bundler/extract.js b/lib/manager/bundler/extract.js
index 6d6adaca638eceaf0bcc85260247fe1ef1a21a85..83ae41780519d1cc9f06f2132b94be0793f9c856 100644
--- a/lib/manager/bundler/extract.js
+++ b/lib/manager/bundler/extract.js
@@ -38,7 +38,7 @@ async function extractPackageFile(content, fileName) {
         dep.skipReason = 'no-version';
       }
       if (!dep.skipReason) {
-        dep.purl = 'pkg:rubygems/' + dep.depName;
+        dep.datasource = 'rubygems';
       }
       res.deps.push(dep);
     }
diff --git a/lib/manager/circleci/extract.js b/lib/manager/circleci/extract.js
index d828e5ac8b31dd5f65e77a8b8e8f5b933881194d..e7e6b5c2c477c36fd581fde5fa86ae97e0a57b34 100644
--- a/lib/manager/circleci/extract.js
+++ b/lib/manager/circleci/extract.js
@@ -30,7 +30,8 @@ function extractPackageFile(content) {
               depName,
               currentValue,
               lineNumber,
-              purl: 'pkg:orb/' + orbName,
+              datasource: 'orb',
+              lookupName: orbName,
               commitMessageTopic: '{{{depName}}} orb',
               versionScheme: 'npm',
               rangeStrategy: 'pin',
diff --git a/lib/manager/composer/extract.js b/lib/manager/composer/extract.js
index 9e508c04e932bece75a8a97817b4228575940e01..94c496993b984c576fe6601fdd8523372a1d804e 100644
--- a/lib/manager/composer/extract.js
+++ b/lib/manager/composer/extract.js
@@ -27,7 +27,7 @@ async function extractPackageFile(content, fileName) {
             depType,
             depName,
             currentValue,
-            purl: 'pkg:packagist/' + depName,
+            datasource: 'packagist',
           };
           if (!depName.includes('/')) {
             dep.skipReason = 'unsupported';
diff --git a/lib/manager/dockerfile/extract.js b/lib/manager/dockerfile/extract.js
index 79934fc344bc2d27ff614e033bd611bd548e4f87..e6fc8171d10236ed3097be5e0e0cd0f2213d9055 100644
--- a/lib/manager/dockerfile/extract.js
+++ b/lib/manager/dockerfile/extract.js
@@ -27,7 +27,7 @@ function getDep(currentFrom) {
     ...splitImageParts(currentFrom),
     currentFrom,
   };
-  dep.purl = `pkg:docker/${dep.depName}`;
+  dep.datasource = 'docker';
   if (
     dep.depName &&
     (dep.depName === 'node' || dep.depName.endsWith('/node')) &&
diff --git a/lib/manager/gomod/extract.js b/lib/manager/gomod/extract.js
index 751279713503719deb55d160837d3c996931b90e..ebecff21aca73e4714860deafc41dfa4eab20836 100644
--- a/lib/manager/gomod/extract.js
+++ b/lib/manager/gomod/extract.js
@@ -25,7 +25,7 @@ function getDep(lineNumber, match) {
     } else {
       dep.depNameShort = depName;
     }
-    dep.purl = `pkg:go/${depName}`;
+    dep.datasource = 'go';
   }
   const digestMatch = currentValue.match(/v0\.0.0-\d{14}-([a-f0-9]{12})/);
   if (digestMatch) {
diff --git a/lib/manager/gradle-wrapper/extract.js b/lib/manager/gradle-wrapper/extract.js
index 63aad2ce4632292f6977cfefb105105976469c52..3136142a8a45b36168fb5f86491ff3b35fbcd130 100644
--- a/lib/manager/gradle-wrapper/extract.js
+++ b/lib/manager/gradle-wrapper/extract.js
@@ -15,7 +15,7 @@ function extractPackageFile(fileContent) {
     );
     if (match) {
       const dependency = {
-        purl: 'pkg:gradleVersion',
+        datasource: 'gradleVersion',
         depType: 'gradle-wrapper',
         depName: 'gradle',
         currentValue: coerce(match[1]).toString(),
diff --git a/lib/manager/maven/extract.js b/lib/manager/maven/extract.js
index e6bc3fff346d36352e6c08dc3451457b0f5e239d..e35460f12b9c7808d0aa4fcc3478221ae38f6312 100644
--- a/lib/manager/maven/extract.js
+++ b/lib/manager/maven/extract.js
@@ -39,9 +39,8 @@ function depFromNode(node) {
       const versionNode = node.descendantWithPath('version');
       const offset = '<version>'.length - 1;
       result.fileReplacePosition = versionNode.startTagPosition + offset;
-      result.purl = `pkg:maven/${
-        result.depName
-      }?repository_url=https://repo.maven.apache.org/maven2`;
+      result.datasource = 'maven';
+      result.registryUrls = ['https://repo.maven.apache.org/maven2'];
     }
     return result;
   }
diff --git a/lib/manager/meteor/extract.js b/lib/manager/meteor/extract.js
index ec84cc5c514b547bd9adbb2bd038138cae9e8fe1..0769c8ed007572c908dd3ad547e7e1ae543f8110 100644
--- a/lib/manager/meteor/extract.js
+++ b/lib/manager/meteor/extract.js
@@ -24,7 +24,7 @@ function extractPackageFile(content) {
         return {
           depName,
           currentValue,
-          purl: `pkg:npm/${depName.replace('@', '%40')}`,
+          datasource: 'npm',
         };
       })
       .filter(dep => dep.depName && dep.currentValue);
diff --git a/lib/manager/npm/extract/index.js b/lib/manager/npm/extract/index.js
index 2c6ac89c970da6b42577ab0d29f6215e5042852a..9d4919e29d3521d5d1ad85cc21c938c4c187970e 100644
--- a/lib/manager/npm/extract/index.js
+++ b/lib/manager/npm/extract/index.js
@@ -144,13 +144,14 @@ async function extractPackageFile(content, fileName, config) {
     dep.currentValue = input.trim();
     if (depType === 'engines') {
       if (depName === 'node') {
-        dep.purl = 'pkg:github/nodejs/node';
+        dep.datasource = 'github';
+        dep.lookupName = 'nodejs/node';
         dep.versionScheme = 'node';
       } else if (depName === 'yarn') {
-        dep.purl = 'pkg:npm/yarn';
+        dep.datasource = 'npm';
         dep.commitMessageTopic = 'Yarn';
       } else if (depName === 'npm') {
-        dep.purl = 'pkg:npm/npm';
+        dep.datasource = 'npm';
         dep.commitMessageTopic = 'npm';
       } else {
         dep.skipReason = 'unknown-engines';
@@ -166,7 +167,7 @@ async function extractPackageFile(content, fileName, config) {
       return dep;
     }
     if (semver.isValid(dep.currentValue)) {
-      dep.purl = `pkg:npm/${depName.replace('@', '%40')}`;
+      dep.datasource = 'npm';
       if (dep.currentValue === '*') {
         dep.skipReason = 'any-version';
       }
@@ -203,7 +204,8 @@ async function extractPackageFile(content, fileName, config) {
     if (semver.isVersion(depRefPart)) {
       dep.currentRawValue = dep.currentValue;
       dep.currentValue = depRefPart;
-      dep.purl = `pkg:github/${githubOwnerRepo}`;
+      dep.datasource = 'github';
+      dep.lookupName = githubOwnerRepo;
       dep.pinDigests = false;
     } else if (
       depRefPart.match(/^[0-9a-f]{7}$/) ||
@@ -212,7 +214,8 @@ async function extractPackageFile(content, fileName, config) {
       dep.currentRawValue = dep.currentValue;
       dep.currentValue = null;
       dep.currentDigest = depRefPart;
-      dep.purl = `pkg:github/${githubOwnerRepo}`;
+      dep.datasource = 'github';
+      dep.lookupName = githubOwnerRepo;
     } else {
       dep.skipReason = 'unversioned-reference';
       return dep;
diff --git a/lib/manager/nuget/extract.js b/lib/manager/nuget/extract.js
index c91664d847921ad6ff64dd0c7d7f164313f62784..e2687b6225faa916e6519e0cecbeed31ecb8fb6e 100644
--- a/lib/manager/nuget/extract.js
+++ b/lib/manager/nuget/extract.js
@@ -21,7 +21,7 @@ function extractPackageFile(content) {
         depName,
         currentValue,
         lineNumber,
-        purl: 'pkg:nuget/' + depName,
+        datasource: 'nuget',
       };
       if (!isVersion(currentValue)) {
         dep.skipReason = 'not-version';
diff --git a/lib/manager/nvm/extract.js b/lib/manager/nvm/extract.js
index 8f7027caba28b07a4c68f566d6d5003ecac07066..25d5725b7e191f8cbd68ebb7873599fdc4b53887 100644
--- a/lib/manager/nvm/extract.js
+++ b/lib/manager/nvm/extract.js
@@ -8,7 +8,8 @@ function extractPackageFile(content) {
   const dep = {
     depName: 'node',
     currentValue: content.trim(),
-    purl: 'pkg:github/nodejs/node',
+    datasource: 'github',
+    lookupName: 'nodejs/node',
   };
   if (!node.isValid(dep.currentValue)) {
     dep.skipReason = 'unsupported-version';
diff --git a/lib/manager/pip_requirements/extract.js b/lib/manager/pip_requirements/extract.js
index 946ca45bedfbcf5e25f939fbda5e4908ab579060..657d919cd1a764ce593cb4bb84fb791b28a8291a 100644
--- a/lib/manager/pip_requirements/extract.js
+++ b/lib/manager/pip_requirements/extract.js
@@ -46,7 +46,7 @@ function extractPackageFile(content) {
         depName,
         currentValue,
         lineNumber,
-        purl: 'pkg:pypi/' + depName,
+        datasource: 'pypi',
       };
       if (registryUrls) {
         dep.registryUrls = registryUrls;
diff --git a/lib/manager/pip_setup/extract.js b/lib/manager/pip_setup/extract.js
index 89574935d53c172d065757e5b58455c818fb8394..dec10189025e76951b458ee1943fa7b520d19a20 100644
--- a/lib/manager/pip_setup/extract.js
+++ b/lib/manager/pip_setup/extract.js
@@ -99,7 +99,7 @@ async function extractPackageFile(content, packageFile, config) {
         depName,
         currentValue,
         lineNumber,
-        purl: 'pkg:pypi/' + depName,
+        datasource: 'pypi',
       };
       return dep;
     })
diff --git a/lib/manager/pipenv/extract.js b/lib/manager/pipenv/extract.js
index 080f49c717da0840e5d64d1d7b74852d951de3d2..17414ab15b80286c805baf68859b37a1b81ac389 100644
--- a/lib/manager/pipenv/extract.js
+++ b/lib/manager/pipenv/extract.js
@@ -75,7 +75,7 @@ function extractFromSection(pipfile, section, registryUrls) {
         depName,
         currentValue,
         pipenvNestedVersion,
-        purl: 'pkg:pypi/' + depName,
+        datasource: 'pypi',
         depType: section,
       };
       if (registryUrls) {
diff --git a/lib/manager/terraform/extract.js b/lib/manager/terraform/extract.js
index 574948f303fee425ad87fffcd6097f1d604aab1b..328e79b12df317038ab34b54a6140028d8d1c8b4 100644
--- a/lib/manager/terraform/extract.js
+++ b/lib/manager/terraform/extract.js
@@ -54,7 +54,8 @@ function extractPackageFile(content) {
       dep.depName = 'github.com/' + githubRefMatch[2];
       dep.depNameShort = githubRefMatch[2];
       dep.currentValue = githubRefMatch[3];
-      dep.purl = 'pkg:github/' + githubRefMatch[2];
+      dep.datasource = 'github';
+      dep.lookupName = githubRefMatch[2];
       dep.lineNumber = dep.sourceLine;
       if (!isVersion(dep.currentValue)) {
         dep.skipReason = 'unsupported-version';
@@ -68,7 +69,7 @@ function extractPackageFile(content) {
         dep.depName = moduleParts.join('/');
         dep.depNameShort = dep.depName;
         dep.lineNumber = dep.versionLine;
-        dep.purl = 'pkg:terraform/' + dep.depName;
+        dep.datasource = 'terraform';
       }
       if (dep.lineNumber) {
         if (!isValid(dep.currentValue)) {
diff --git a/lib/manager/travis/package.js b/lib/manager/travis/package.js
index 07221490030172fdc3e2386899f161674012cd5d..39d14d51ffdb39486ce75ef4c534d152f40ef42a 100644
--- a/lib/manager/travis/package.js
+++ b/lib/manager/travis/package.js
@@ -37,7 +37,8 @@ async function getPackageUpdates(config) {
   if (config.rangeStrategy === 'pin' || isVersion(config.currentValue[0])) {
     const versions = (await getPkgReleases({
       ...config,
-      purl: 'pkg:github/nodejs/node',
+      datasource: 'github',
+      depName: 'nodejs/node',
     })).releases.map(release => release.version);
     newValue = newValue.map(value =>
       maxSatisfyingVersion(versions, `${value}`)
diff --git a/lib/util/purl.js b/lib/util/purl.js
deleted file mode 100644
index 08b4d57d0e7971cceadd05cffb31684d139c65a7..0000000000000000000000000000000000000000
--- a/lib/util/purl.js
+++ /dev/null
@@ -1,58 +0,0 @@
-module.exports = {
-  parse,
-};
-
-function parse(input) {
-  if (!input) {
-    return null;
-  }
-  const scheme = 'pkg:';
-  if (!input.startsWith(scheme)) {
-    return null;
-  }
-  const purl = {};
-  let remaining = input.substring(scheme.length);
-  let parts = remaining.split('#');
-  if (parts.length > 1) {
-    [remaining, purl.subpath] = parts;
-  }
-  parts = remaining.split('?');
-  if (parts.length > 1) {
-    [remaining, purl.qualifiers] = parts;
-  }
-  parts = remaining.split('@');
-  if (parts.length > 1) {
-    [remaining, purl.version] = parts;
-  }
-  parts = remaining.split('/');
-  [purl.type, ...remaining] = parts;
-  if (remaining.length === 1) {
-    [purl.name] = remaining;
-    purl.fullname = purl.name;
-  } else {
-    purl.name = remaining.pop();
-    purl.namespace = remaining.join('/').replace('%40', '@');
-    purl.fullname = purl.namespace + '/' + purl.name;
-  }
-  if (purl.qualifiers) {
-    const allQualifiers = purl.qualifiers.split('&');
-    purl.qualifiers = {};
-    allQualifiers.forEach(qualifier => {
-      const [key, val] = qualifier.split('=');
-      purl.qualifiers[key] = val;
-    });
-  } else {
-    purl.qualifiers = {};
-  }
-  const res = {
-    datasource: purl.type,
-    lookupName: purl.fullname,
-  };
-  if (purl.qualifiers.repository_url) {
-    res.registryUrls = purl.qualifiers.repository_url.split(',');
-  }
-  if (purl.subpath) {
-    res.lookupType = purl.subpath;
-  }
-  return res;
-}
diff --git a/lib/workers/repository/process/fetch.js b/lib/workers/repository/process/fetch.js
index 5f758f1d899cf205aaced757b0dba37fddbdcb3e..2adaeccabf315388060835ebb9846c9dc849315c 100644
--- a/lib/workers/repository/process/fetch.js
+++ b/lib/workers/repository/process/fetch.js
@@ -38,7 +38,7 @@ async function fetchDepUpdates(packageFileConfig, dep) {
     dep.skipReason = 'disabled';
   } else {
     let lookupResults;
-    if (depConfig.purl) {
+    if (depConfig.datasource) {
       lookupResults = await lookupUpdates(depConfig);
     } else {
       lookupResults = await getPackageUpdates(manager, depConfig);
diff --git a/lib/workers/repository/process/lookup/index.js b/lib/workers/repository/process/lookup/index.js
index 9dd5ca673aca9f318cd53bd8b7d0d1ab4db2d152..b47a1eb00079c3ef3edb97c1b137f69b49889b25 100644
--- a/lib/workers/repository/process/lookup/index.js
+++ b/lib/workers/repository/process/lookup/index.js
@@ -64,10 +64,7 @@ async function lookupUpdates(config) {
     // istanbul ignore if
     if (allVersions.length === 0) {
       const message = `No valid versions returned from registry for this package`;
-      logger.debug(
-        { purl: config.purl, dependency: depName, result: dependency },
-        message
-      );
+      logger.debug({ dependency: depName, result: dependency }, message);
       if (!config.currentDigest) {
         return res;
       }
@@ -211,7 +208,7 @@ async function lookupUpdates(config) {
     }
   }
   // Add digests if necessary
-  if (supportsDigests(config.purl)) {
+  if (supportsDigests(config)) {
     if (config.currentDigest) {
       if (!config.digestOneAndOnly || !res.updates.length) {
         // digest update
@@ -249,10 +246,7 @@ async function lookupUpdates(config) {
             .replace('sha256:', '')
             .substring(0, 7);
         } else {
-          logger.info(
-            { purl: config.purl, newValue: update.newValue },
-            'Could not getDigest'
-          );
+          logger.info({ newValue: update.newValue }, 'Could not getDigest');
         }
       }
     }
diff --git a/test/datasource/__snapshots__/go.spec.js.snap b/test/datasource/__snapshots__/go.spec.js.snap
index 72403b21d62617b631fcd628602877fd929982de..a0512c38f284bb3112acd0bfe3b9efdcfe3c7b92 100644
--- a/test/datasource/__snapshots__/go.spec.js.snap
+++ b/test/datasource/__snapshots__/go.spec.js.snap
@@ -17,16 +17,19 @@ exports[`datasource/go getPkgReleases works for known servers 1`] = `
 Array [
   Array [
     Object {
+      "datasource": "github",
       "lookupName": "x/text",
     },
   ],
   Array [
     Object {
+      "datasource": "github",
       "lookupName": "x/text",
     },
   ],
   Array [
     Object {
+      "datasource": "github",
       "lookupName": "go-x/x",
     },
   ],
diff --git a/test/datasource/docker.spec.js b/test/datasource/docker.spec.js
index e8afa67f902422498621bb3bf5f75ac703e60d9d..812b5aa43982c05a91070149e0b3d9e886189d74 100644
--- a/test/datasource/docker.spec.js
+++ b/test/datasource/docker.spec.js
@@ -20,7 +20,7 @@ describe('api/docker', () => {
     it('returns null if no token', async () => {
       got.mockReturnValueOnce({ body: {} });
       const res = await docker.getDigest(
-        { depName: 'some-dep' },
+        { lookupName: 'some-dep' },
         'some-new-value'
       );
       expect(res).toBe(null);
@@ -28,7 +28,7 @@ describe('api/docker', () => {
     it('returns null if errored', async () => {
       got.mockReturnValueOnce({ body: { token: 'some-token' } });
       const res = await docker.getDigest(
-        { depName: 'some-dep' },
+        { lookupName: 'some-dep' },
         'some-new-value'
       );
       expect(res).toBe(null);
@@ -45,7 +45,7 @@ describe('api/docker', () => {
         headers: { 'docker-content-digest': 'some-digest' },
       });
       const res = await docker.getDigest(
-        { depName: 'some-dep' },
+        { lookupName: 'some-dep' },
         'some-new-value'
       );
       expect(res).toBe('some-digest');
@@ -82,7 +82,7 @@ describe('api/docker', () => {
        }`,
       });
       const res = await docker.getDigest(
-        { depName: 'some-dep' },
+        { lookupName: 'some-dep' },
         'some-new-value'
       );
       expect(res).toBe(
@@ -101,7 +101,10 @@ describe('api/docker', () => {
       got.mockReturnValueOnce({
         headers: { 'docker-content-digest': 'some-digest' },
       });
-      const res = await docker.getDigest({ depName: 'some-dep' }, 'some-tag');
+      const res = await docker.getDigest(
+        { lookupName: 'some-dep' },
+        'some-tag'
+      );
       expect(got.mock.calls[1][1].headers.Authorization).toBe(
         'Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk'
       );
@@ -116,7 +119,10 @@ describe('api/docker', () => {
       got.mockReturnValueOnce({
         statusCode: 403,
       });
-      const res = await docker.getDigest({ depName: 'some-dep' }, 'some-tag');
+      const res = await docker.getDigest(
+        { lookupName: 'some-dep' },
+        'some-tag'
+      );
       expect(res).toBeNull();
     });
     it('continues without token, when no header is present', async () => {
@@ -129,7 +135,7 @@ describe('api/docker', () => {
         headers: { 'docker-content-digest': 'some-digest' },
       });
       const res = await docker.getDigest(
-        { depName: 'some-dep' },
+        { lookupName: 'some-dep' },
         'some-new-value'
       );
       expect(res).toBe('some-digest');
@@ -146,7 +152,7 @@ describe('api/docker', () => {
         headers: { 'docker-content-digest': 'some-digest' },
       });
       const res = await docker.getDigest(
-        { depName: 'some-dep' },
+        { lookupName: 'some-dep' },
         '8.0.0-alpine'
       );
       expect(res).toBe('some-digest');
@@ -155,7 +161,7 @@ describe('api/docker', () => {
       got.mockRejectedValueOnce({ statusCode: 429 });
       let e;
       try {
-        await docker.getDigest({ depName: 'some-dep' }, 'latest');
+        await docker.getDigest({ lookupName: 'some-dep' }, 'latest');
       } catch (err) {
         e = err;
       }
@@ -165,7 +171,7 @@ describe('api/docker', () => {
       got.mockRejectedValueOnce({ statusCode: 503 });
       let e;
       try {
-        await docker.getDigest({ depName: 'some-dep' }, 'latest');
+        await docker.getDigest({ lookupName: 'some-dep' }, 'latest');
       } catch (err) {
         e = err;
       }
@@ -180,7 +186,10 @@ describe('api/docker', () => {
     });
     it('returns null if no token', async () => {
       got.mockReturnValueOnce({ body: {} });
-      const res = await getPkgReleases({ purl: 'pkg:docker/node' });
+      const res = await getPkgReleases({
+        datasource: 'docker',
+        depName: 'node',
+      });
       expect(res).toBe(null);
     });
     it('uses custom registry with registryUrls', async () => {
@@ -190,9 +199,11 @@ describe('api/docker', () => {
       });
       got.mockReturnValueOnce({ headers: {}, body: { tags } });
       const config = {
+        datasource: 'docker',
+        depName: 'node',
         registryUrls: ['https://registry.company.com'],
       };
-      const res = await getPkgReleases({ ...config, purl: 'pkg:docker/node' });
+      const res = await getPkgReleases(config);
       expect(res.releases).toHaveLength(1);
       expect(got.mock.calls).toMatchSnapshot();
       expect(got.mock.calls[0][0].startsWith(config.registryUrls[0])).toBe(
@@ -206,7 +217,8 @@ describe('api/docker', () => {
       });
       got.mockReturnValueOnce({ headers: {}, body: { tags } });
       const res = await getPkgReleases({
-        purl: 'pkg:docker/registry.company.com/node',
+        datasource: 'docker',
+        depName: 'registry.company.com/node',
       });
       expect(res.releases).toHaveLength(1);
       expect(got).toMatchSnapshot();
@@ -221,7 +233,10 @@ describe('api/docker', () => {
       });
       got.mockReturnValueOnce({ headers: {}, body: { token: 'some-token ' } });
       got.mockReturnValueOnce({ headers: {}, body: { tags } });
-      const res = await getPkgReleases({ purl: 'pkg:docker/node' });
+      const res = await getPkgReleases({
+        datasource: 'docker',
+        depName: 'node',
+      });
       expect(res.releases).toHaveLength(1);
       expect(got).toMatchSnapshot();
     });
@@ -236,7 +251,8 @@ describe('api/docker', () => {
       got.mockReturnValueOnce({ headers: {}, body: { token: 'some-token ' } });
       got.mockReturnValueOnce({ headers: {}, body: { tags } });
       const res = await getPkgReleases({
-        purl: 'pkg:docker/docker.io/node',
+        datasource: 'docker',
+        depName: 'docker.io/node',
       });
       expect(res.releases).toHaveLength(1);
       expect(got).toMatchSnapshot();
@@ -252,7 +268,8 @@ describe('api/docker', () => {
       got.mockReturnValueOnce({ headers: {}, body: { token: 'some-token ' } });
       got.mockReturnValueOnce({ headers: {}, body: { tags } });
       const res = await getPkgReleases({
-        purl: 'pkg:docker/k8s.gcr.io/kubernetes-dashboard-amd64',
+        datasource: 'docker',
+        depName: 'k8s.gcr.io/kubernetes-dashboard-amd64',
       });
       expect(res.releases).toHaveLength(1);
       expect(got).toMatchSnapshot();
diff --git a/test/datasource/github.spec.js b/test/datasource/github.spec.js
index ef3e21bf3aa9519dd7d6c6340b3fda8474644d4e..046635f3677fb4c486cc33e0e8058bab7404dda4 100644
--- a/test/datasource/github.spec.js
+++ b/test/datasource/github.spec.js
@@ -24,7 +24,7 @@ describe('datasource/github', () => {
     it('returns digest', async () => {
       ghGot.mockReturnValueOnce({ body: [{ sha: 'abcdef' }] });
       const res = await github.getDigest(
-        { depName: 'some-dep', purl: 'pkg:github/some/dep?foo=1' },
+        { depName: 'some-dep', lookupName: 'some/dep' },
         null
       );
       expect(res).toBe('abcdef');
@@ -71,7 +71,9 @@ describe('datasource/github', () => {
       ];
       ghGot.mockReturnValueOnce({ headers: {}, body });
       const res = await datasource.getPkgReleases({
-        purl: 'pkg:github/some/dep#releases',
+        datasource: 'github',
+        depName: 'some/dep',
+        lookupType: 'releases',
       });
       expect(res).toMatchSnapshot();
       expect(res.releases).toHaveLength(2);
@@ -83,17 +85,11 @@ describe('datasource/github', () => {
       const body = [{ name: 'v1.0.0' }, { name: 'v1.1.0' }];
       ghGot.mockReturnValueOnce({ headers: {}, body });
       const res = await datasource.getPkgReleases({
-        purl: 'pkg:github/some/dep2',
+        datasource: 'github',
+        depName: 'some/dep2',
       });
       expect(res).toMatchSnapshot();
       expect(res.releases).toHaveLength(2);
     });
-    it('returns null for invalid ref', async () => {
-      expect(
-        await datasource.getPkgReleases({
-          purl: 'pkg:github/some/dep?ref=invalid',
-        })
-      ).toBeNull();
-    });
   });
 });
diff --git a/test/datasource/gitlab.spec.js b/test/datasource/gitlab.spec.js
index 0051d407d64ed2bd2c80149812fb766c1022aaf5..56b63ce31df7e54ad7382198416ae6cbfec5de97 100644
--- a/test/datasource/gitlab.spec.js
+++ b/test/datasource/gitlab.spec.js
@@ -1,4 +1,3 @@
-const datasource = require('../../lib/datasource');
 const gitlab = require('../../lib/datasource/gitlab');
 const glGot = require('../../lib/platform/gitlab/gl-got-wrapper');
 
@@ -48,14 +47,4 @@ describe('datasource/gitlab', () => {
       expect(content).toEqual({ foo: 'bar' });
     });
   });
-  describe('getPkgReleases', () => {
-    beforeAll(() => global.renovateCache.rmAll());
-    it('returns null for invalid ref', async () => {
-      expect(
-        await datasource.getPkgReleases({
-          purl: 'pkg:github/some/dep?ref=invalid',
-        })
-      ).toBeNull();
-    });
-  });
 });
diff --git a/test/datasource/go.spec.js b/test/datasource/go.spec.js
index 356528dcc59b9b48bd06fa317c70f41a5e189a42..476fbf8212b16353c23af3dc3dd13f84ac249926 100644
--- a/test/datasource/go.spec.js
+++ b/test/datasource/go.spec.js
@@ -1,5 +1,4 @@
 const got = require('../../lib/util/got');
-const datasource = require('../../lib/datasource');
 const github = require('../../lib/datasource/github');
 const go = require('../../lib/datasource/go');
 
@@ -23,13 +22,13 @@ describe('datasource/go', () => {
   beforeEach(() => {
     global.repoCache = {};
   });
-  describe('getPkgReleases', () => {
+  describe('getDigest', () => {
     it('returns null for wrong name', async () => {
       got.mockReturnValueOnce({
         body: res1,
       });
       github.getDigest.mockReturnValueOnce('abcdefabcdefabcdefabcdef');
-      const res = await go.getDigest({ depName: 'golang.org/y/text' }, null);
+      const res = await go.getDigest({ lookupName: 'golang.org/y/text' }, null);
       expect(res).toBeNull();
     });
     it('returns digest', async () => {
@@ -37,7 +36,7 @@ describe('datasource/go', () => {
         body: res1,
       });
       github.getDigest.mockReturnValueOnce('abcdefabcdefabcdefabcdef');
-      const res = await go.getDigest({ depName: 'golang.org/x/text' }, null);
+      const res = await go.getDigest({ lookupName: 'golang.org/x/text' }, null);
       expect(res).toBe('abcdefabcdefabcdefabcdef');
     });
   });
@@ -45,8 +44,8 @@ describe('datasource/go', () => {
     it('returns null for empty result', async () => {
       got.mockReturnValueOnce(null);
       expect(
-        await datasource.getPkgReleases({
-          purl: 'pkg:go/golang.org/foo/something',
+        await go.getPkgReleases({
+          lookupName: 'golang.org/foo/something',
         })
       ).toBeNull();
     });
@@ -57,8 +56,8 @@ describe('datasource/go', () => {
         })
       );
       expect(
-        await datasource.getPkgReleases({
-          purl: 'pkg:go/golang.org/foo/something',
+        await go.getPkgReleases({
+          lookupName: 'golang.org/foo/something',
         })
       ).toBeNull();
     });
@@ -67,8 +66,8 @@ describe('datasource/go', () => {
         throw new Error();
       });
       expect(
-        await datasource.getPkgReleases({
-          purl: 'pkg:go/golang.org/foo/something',
+        await go.getPkgReleases({
+          lookupName: 'golang.org/foo/something',
         })
       ).toBeNull();
     });
@@ -79,8 +78,8 @@ describe('datasource/go', () => {
       github.getPkgReleases.mockReturnValueOnce({
         releases: [{ version: 'v1.0.0' }, { version: 'v2.0.0' }],
       });
-      const res = await datasource.getPkgReleases({
-        purl: 'pkg:go/golang.org/x/text',
+      const res = await go.getPkgReleases({
+        lookupName: 'golang.org/x/text',
       });
       expect(res).toMatchSnapshot();
       expect(res).not.toBeNull();
@@ -90,8 +89,8 @@ describe('datasource/go', () => {
       got.mockReturnValueOnce({
         body: res1,
       });
-      const res = await datasource.getPkgReleases({
-        purl: 'pkg:go/golang.org/x/sys',
+      const res = await go.getPkgReleases({
+        lookupName: 'golang.org/x/sys',
       });
       expect(res).toBeNull();
     });
@@ -102,8 +101,8 @@ describe('datasource/go', () => {
           'https://google.com/golang/text/'
         ),
       });
-      const res = await datasource.getPkgReleases({
-        purl: 'pkg:go/golang.org/x/text',
+      const res = await go.getPkgReleases({
+        lookupName: 'golang.org/x/text',
       });
       expect(res).toBeNull();
     });
@@ -111,14 +110,14 @@ describe('datasource/go', () => {
       got.mockClear();
       github.getPkgReleases.mockClear();
       const packages = [
-        { purl: 'pkg:go/github.com/x/text' },
-        { purl: 'pkg:go/gopkg.in/x/text' },
-        { purl: 'pkg:go/gopkg.in/x' },
+        { lookupName: 'github.com/x/text' },
+        { lookupName: 'gopkg.in/x/text' },
+        { lookupName: 'gopkg.in/x' },
       ];
       const githubRes = { releases: [1, 2] };
       for (const pkg of packages) {
         github.getPkgReleases.mockReturnValueOnce(githubRes);
-        expect(await datasource.getPkgReleases(pkg)).toEqual(githubRes);
+        expect(await go.getPkgReleases(pkg)).toEqual(githubRes);
       }
       expect(got.mock.calls).toHaveLength(0);
       expect(github.getPkgReleases.mock.calls).toMatchSnapshot();
diff --git a/test/datasource/gradle-version.spec.js b/test/datasource/gradle-version.spec.js
index cf38f69100b69687f4994539583ffd51850edff6..aff94a75c02ef2229af63689c46083d01e25a031 100644
--- a/test/datasource/gradle-version.spec.js
+++ b/test/datasource/gradle-version.spec.js
@@ -12,6 +12,7 @@ describe('datasource/gradle', () => {
   describe('getPkgReleases', () => {
     beforeEach(() => {
       config = {
+        datasource: 'gradleVersion',
         gradleWrapperType: 'bin',
         typeStrategy: 'auto',
         digests: 'true',
@@ -25,7 +26,9 @@ describe('datasource/gradle', () => {
     it('returns null for empty result', async () => {
       got.mockReturnValueOnce({ body: {} });
       expect(
-        await datasource.getPkgReleases({ purl: 'pkg:gradleVersion' }, config)
+        await datasource.getPkgReleases({
+          ...config,
+        })
       ).toBeNull();
     });
 
@@ -37,7 +40,9 @@ describe('datasource/gradle', () => {
       );
       let e;
       try {
-        await datasource.getPkgReleases({ purl: 'pkg:gradleVersion' }, config);
+        await datasource.getPkgReleases({
+          ...config,
+        });
       } catch (err) {
         e = err;
       }
@@ -48,19 +53,14 @@ describe('datasource/gradle', () => {
       got.mockImplementationOnce(() => {
         throw new Error();
       });
-      expect(
-        await datasource.getPkgReleases({ purl: 'pkg:gradleVersion' }, config)
-      ).toBeNull();
+      expect(await datasource.getPkgReleases(config)).toBeNull();
     });
 
     it('processes real data', async () => {
       got.mockReturnValueOnce({
         body: JSON.parse(allResponse),
       });
-      const res = await datasource.getPkgReleases(
-        { purl: 'pkg:gradleVersion' },
-        config
-      );
+      const res = await datasource.getPkgReleases(config);
       expect(res).toMatchSnapshot();
       expect(res).not.toBeNull();
     });
diff --git a/test/datasource/index.spec.js b/test/datasource/index.spec.js
index f69d2be0b013dce1e83cf87b794a70b3a520c5da..b752e9224a4d03f128e8373e3558c12a0c4cff31 100644
--- a/test/datasource/index.spec.js
+++ b/test/datasource/index.spec.js
@@ -6,27 +6,38 @@ jest.mock('../../lib/datasource/npm');
 
 describe('datasource/index', () => {
   it('returns if digests are supported', async () => {
-    expect(await datasource.supportsDigests('pkg:github/some/dep')).toBe(true);
+    expect(await datasource.supportsDigests({ datasource: 'github' })).toBe(
+      true
+    );
   });
-  it('returns null for unknown datasource', async () => {
+  it('returns null for no datasource', async () => {
     expect(
-      await datasource.getPkgReleases({ purl: 'pkg:gitbucket/some/dep' })
+      await datasource.getPkgReleases({
+        depName: 'some/dep',
+      })
     ).toBeNull();
   });
-  it('returns null for invalid purl', async () => {
+  it('returns null for unknown datasource', async () => {
     expect(
-      await datasource.getPkgReleases({ purl: 'pkggithub/some/dep' })
+      await datasource.getPkgReleases({
+        datasource: 'gitbucket',
+        depName: 'some/dep',
+      })
     ).toBeNull();
   });
   it('returns getDigest', async () => {
     expect(
-      await datasource.getDigest({ purl: 'pkg:docker/node' })
+      await datasource.getDigest({
+        datasource: 'docker',
+        depName: 'docker/node',
+      })
     ).toBeUndefined();
   });
   it('adds changelogUrl', async () => {
     npmDatasource.getPkgReleases.mockReturnValue({});
     const res = await datasource.getPkgReleases({
-      purl: 'pkg:npm/react-native',
+      datasource: 'npm',
+      depName: 'react-native',
     });
     expect(res).toMatchSnapshot();
     expect(res.changelogUrl).toBeDefined();
@@ -34,7 +45,10 @@ describe('datasource/index', () => {
   });
   it('adds sourceUrl', async () => {
     npmDatasource.getPkgReleases.mockReturnValue({});
-    const res = await datasource.getPkgReleases({ purl: 'pkg:npm/node' });
+    const res = await datasource.getPkgReleases({
+      datasource: 'npm',
+      depName: 'node',
+    });
     expect(res).toMatchSnapshot();
     expect(res.sourceUrl).toBeDefined();
   });
diff --git a/test/datasource/maven.spec.js b/test/datasource/maven.spec.js
index 63c48b1bbaeb74b21460f42bb43f39a709b34062..56b42d72a10d8481edb742e57e41d7f5a86ef0fe 100644
--- a/test/datasource/maven.spec.js
+++ b/test/datasource/maven.spec.js
@@ -27,6 +27,7 @@ const MYSQL_MAVEN_MYSQL_POM = fs.readFileSync(
 );
 
 const config = {
+  datasource: 'maven',
   versionScheme: 'loose',
 };
 
@@ -52,8 +53,10 @@ describe('datasource/maven', () => {
     it('should return empty if library is not found', async () => {
       const releases = await datasource.getPkgReleases({
         ...config,
-        purl:
-          'pkg:maven/unknown/unknown?repository_url=file://test/_fixtures/gradle/maven/repo1.maven.org/maven2/',
+        lookupName: 'unknown/unknown',
+        registryUrls: [
+          'file://test/_fixtures/gradle/maven/repo1.maven.org/maven2/',
+        ],
       });
       expect(releases).toBeNull();
     });
@@ -61,8 +64,11 @@ describe('datasource/maven', () => {
     it('should simply return all versions of a specific library', async () => {
       const releases = await datasource.getPkgReleases({
         ...config,
-        purl:
-          'pkg:maven/org.hamcrest/hamcrest-core?repository_url=file://test/_fixtures/gradle/maven/repo1.maven.org/maven2/,file://test/_fixtures/gradle/maven/custom_maven_repo/maven2/',
+        lookupName: 'org.hamcrest/hamcrest-core',
+        registryUrls: [
+          'file://test/_fixtures/gradle/maven/repo1.maven.org/maven2/',
+          'file://test/_fixtures/gradle/maven/custom_maven_repo/maven2/',
+        ],
       });
       expect(releases.releases).toEqual(
         generateReleases([
@@ -80,8 +86,11 @@ describe('datasource/maven', () => {
     it('should return versions in all repositories for a specific library', async () => {
       const releases = await datasource.getPkgReleases({
         ...config,
-        purl:
-          'pkg:maven/mysql/mysql-connector-java?repository_url=file://test/_fixtures/gradle/maven/repo1.maven.org/maven2/,file://test/_fixtures/gradle/maven/custom_maven_repo/maven2/',
+        lookupName: 'mysql/mysql-connector-java',
+        registryUrls: [
+          'file://test/_fixtures/gradle/maven/repo1.maven.org/maven2/',
+          'file://test/_fixtures/gradle/maven/custom_maven_repo/maven2/',
+        ],
       });
       expect(releases.releases).toEqual(
         generateReleases(['6.0.4', ...MYSQL_VERSIONS])
@@ -91,8 +100,8 @@ describe('datasource/maven', () => {
     it('should return all versions of a specific library for http repositories', async () => {
       const releases = await datasource.getPkgReleases({
         ...config,
-        purl:
-          'pkg:maven/mysql/mysql-connector-java?repository_url=http://central.maven.org/maven2/',
+        lookupName: 'mysql/mysql-connector-java',
+        registryUrls: ['http://central.maven.org/maven2/'],
       });
       expect(releases.releases).toEqual(generateReleases(MYSQL_VERSIONS));
     });
@@ -100,8 +109,13 @@ describe('datasource/maven', () => {
     it('should return all versions of a specific library if a repository fails', async () => {
       const releases = await datasource.getPkgReleases({
         ...config,
-        purl:
-          'pkg:maven/mysql/mysql-connector-java?repository_url=http://central.maven.org/maven2/,http://failed_repo/,http://dns_error_repo,http://empty_repo',
+        lookupName: 'mysql/mysql-connector-java',
+        registryUrls: [
+          'http://central.maven.org/maven2/',
+          'http://failed_repo/',
+          'http://dns_error_repo',
+          'http://empty_repo',
+        ],
       });
       expect(releases.releases).toEqual(generateReleases(MYSQL_VERSIONS));
     });
@@ -116,8 +130,8 @@ describe('datasource/maven', () => {
       try {
         await datasource.getPkgReleases({
           ...config,
-          purl:
-            'pkg:maven/org/artifact?repository_url=http://central.maven.org/maven2/',
+          lookupName: 'org/artifact',
+          registryUrls: ['http://central.maven.org/maven2/'],
         });
       } catch (e) {
         expect(e.message).toEqual('registry-failure');
@@ -127,8 +141,12 @@ describe('datasource/maven', () => {
     it('should return all versions of a specific library if a repository fails because invalid protocol', async () => {
       const releases = await datasource.getPkgReleases({
         ...config,
-        purl:
-          'pkg:maven/mysql/mysql-connector-java?repository_url=http://central.maven.org/maven2/,http://failed_repo/,ftp://protocol_error_repo',
+        lookupName: 'mysql/mysql-connector-java',
+        registryUrls: [
+          'http://central.maven.org/maven2/',
+          'http://failed_repo/',
+          'ftp://protocol_error_repo',
+        ],
       });
       expect(releases.releases).toEqual(generateReleases(MYSQL_VERSIONS));
     });
@@ -149,8 +167,11 @@ describe('datasource/maven', () => {
         .reply(200, invalidMavenMetadata);
       const releases = await datasource.getPkgReleases({
         ...config,
-        purl:
-          'pkg:maven/mysql/mysql-connector-java?repository_url=http://central.maven.org/maven2/,http://invalid_metadata_repo/maven2/',
+        lookupName: 'mysql/mysql-connector-java',
+        registryUrls: [
+          'http://central.maven.org/maven2/',
+          'http://invalid_metadata_repo/maven2/',
+        ],
       });
       expect(releases.releases).toEqual(generateReleases(MYSQL_VERSIONS));
     });
@@ -164,8 +185,11 @@ describe('datasource/maven', () => {
         .reply(200, invalidMavenMetadata);
       const releases = await datasource.getPkgReleases({
         ...config,
-        purl:
-          'pkg:maven/mysql/mysql-connector-java?repository_url=http://central.maven.org/maven2/,http://invalid_metadata_repo/maven2/',
+        lookupName: 'mysql/mysql-connector-java',
+        registryUrls: [
+          'http://central.maven.org/maven2/',
+          'http://invalid_metadata_repo/maven2/',
+        ],
       });
       expect(releases.releases).toEqual(generateReleases(MYSQL_VERSIONS));
     });
@@ -173,8 +197,8 @@ describe('datasource/maven', () => {
     it('should return all versions of a specific library if a repository does not end with /', async () => {
       const releases = await datasource.getPkgReleases({
         ...config,
-        purl:
-          'pkg:maven/mysql/mysql-connector-java?repository_url=http://central.maven.org/maven2',
+        lookupName: 'mysql/mysql-connector-java',
+        registryUrls: ['http://central.maven.org/maven2'],
       });
       expect(releases).not.toBeNull();
     });
@@ -182,7 +206,7 @@ describe('datasource/maven', () => {
     it('should return null if no repositories defined', async () => {
       const releases = await datasource.getPkgReleases({
         ...config,
-        purl: 'pkg:maven/mysql/mysql-connector-java',
+        lookupName: 'mysql/mysql-connector-java',
       });
       expect(releases).toBeNull();
     });
diff --git a/test/datasource/npm/__snapshots__/index.spec.js.snap b/test/datasource/npm/__snapshots__/index.spec.js.snap
index 4e2d135f697b83a80a320bf3bed5e41472051948..beea06339a6befc545cbf91d0d4323a4d96d9583 100644
--- a/test/datasource/npm/__snapshots__/index.spec.js.snap
+++ b/test/datasource/npm/__snapshots__/index.spec.js.snap
@@ -56,7 +56,7 @@ Object {
 }
 `;
 
-exports[`api/npm should handle no time 1`] = `
+exports[`api/npm should handle foobar 1`] = `
 Object {
   "homepage": undefined,
   "latestVersion": "0.0.1",
@@ -69,7 +69,9 @@ Object {
       "version": "0.0.1",
     },
     Object {
+      "canBeUnpublished": false,
       "gitRef": undefined,
+      "releaseTimestamp": "2018-05-07T07:21:53+02:00",
       "version": "0.0.2",
     },
   ],
@@ -82,7 +84,7 @@ Object {
 }
 `;
 
-exports[`api/npm should handle purl 1`] = `
+exports[`api/npm should handle no time 1`] = `
 Object {
   "homepage": undefined,
   "latestVersion": "0.0.1",
@@ -95,9 +97,7 @@ Object {
       "version": "0.0.1",
     },
     Object {
-      "canBeUnpublished": false,
       "gitRef": undefined,
-      "releaseTimestamp": "2018-05-07T07:21:53+02:00",
       "version": "0.0.2",
     },
   ],
diff --git a/test/datasource/npm/index.spec.js b/test/datasource/npm/index.spec.js
index 288863b3ec58c4c05d183e17126f2449259e4b7f..0fef8dbe0ba8e66d7d48e6ab9c3db501eec8188b 100644
--- a/test/datasource/npm/index.spec.js
+++ b/test/datasource/npm/index.spec.js
@@ -201,7 +201,7 @@ describe('api/npm', () => {
     expect(res).toMatchSnapshot();
     expect(res.deprecationMessage).toMatchSnapshot();
   });
-  it('should handle purl', async () => {
+  it('should handle foobar', async () => {
     nock('https://registry.npmjs.org')
       .get('/foobar')
       .reply(200, npmResponse);
@@ -358,7 +358,7 @@ describe('api/npm', () => {
       .get('/foobar')
       .reply(200, npmResponse);
     const npmrc = 'foo=bar';
-    const res = await npm.getPkgReleases({ lookupName: 'foobar' }, { npmrc });
+    const res = await npm.getPkgReleases({ lookupName: 'foobar', npmrc });
     expect(res).toMatchSnapshot();
   });
   it('should cache package info from npm', async () => {
@@ -366,8 +366,8 @@ describe('api/npm', () => {
       .get('/foobar')
       .reply(200, npmResponse);
     const npmrc = '//registry.npmjs.org/:_authToken=abcdefghijklmnopqrstuvwxyz';
-    const res1 = await npm.getPkgReleases({ lookupName: 'foobar' }, { npmrc });
-    const res2 = await npm.getPkgReleases({ lookupName: 'foobar' }, { npmrc });
+    const res1 = await npm.getPkgReleases({ lookupName: 'foobar', npmrc });
+    const res2 = await npm.getPkgReleases({ lookupName: 'foobar', npmrc });
     expect(res1).not.toBe(null);
     expect(res1).toEqual(res2);
   });
@@ -384,7 +384,7 @@ describe('api/npm', () => {
     const npmrc =
       'registry=https://npm.mycustomregistry.com/\n//npm.mycustomregistry.com/:_auth = ' +
       Buffer.from('abcdef').toString('base64');
-    const res = await npm.getPkgReleases({ lookupName: 'foobar' }, { npmrc });
+    const res = await npm.getPkgReleases({ lookupName: 'foobar', npmrc });
     expect(res).toMatchSnapshot();
   });
   it('should replace any environment variable in npmrc', async () => {
@@ -395,7 +395,7 @@ describe('api/npm', () => {
     global.trustLevel = 'high';
     // eslint-disable-next-line no-template-curly-in-string
     const npmrc = 'registry=${REGISTRY}';
-    const res = await npm.getPkgReleases({ lookupName: 'foobar' }, { npmrc });
+    const res = await npm.getPkgReleases({ lookupName: 'foobar', npmrc });
     expect(res).toMatchSnapshot();
   });
   it('should throw error if necessary env var is not present', () => {
diff --git a/test/datasource/nuget.spec.js b/test/datasource/nuget.spec.js
index 1796c337598cdeb9e2eff23d28ff698af8602898..ccdfaa3a6d701b24821a7129272314fc63b27ce0 100644
--- a/test/datasource/nuget.spec.js
+++ b/test/datasource/nuget.spec.js
@@ -15,7 +15,10 @@ describe('datasource/nuget', () => {
     it('returns null for empty result', async () => {
       got.mockReturnValueOnce({});
       expect(
-        await datasource.getPkgReleases({ purl: 'pkg:nuget/something' })
+        await datasource.getPkgReleases({
+          datasource: 'nuget',
+          lookupName: 'something',
+        })
       ).toBeNull();
     });
     it('returns null for 404', async () => {
@@ -25,7 +28,10 @@ describe('datasource/nuget', () => {
         })
       );
       expect(
-        await datasource.getPkgReleases({ purl: 'pkg:nuget/something' })
+        await datasource.getPkgReleases({
+          datasource: 'nuget',
+          lookupName: 'something',
+        })
       ).toBeNull();
     });
     it('returns null for unknown error', async () => {
@@ -33,7 +39,10 @@ describe('datasource/nuget', () => {
         throw new Error();
       });
       expect(
-        await datasource.getPkgReleases({ purl: 'pkg:nuget/something' })
+        await datasource.getPkgReleases({
+          datasource: 'nuget',
+          lookupName: 'something',
+        })
       ).toBeNull();
     });
     it('processes real data', async () => {
@@ -43,7 +52,10 @@ describe('datasource/nuget', () => {
       got.mockReturnValueOnce({
         body: res2,
       });
-      const res = await datasource.getPkgReleases({ purl: 'pkg:nuget/nunit' });
+      const res = await datasource.getPkgReleases({
+        datasource: 'nuget',
+        lookupName: 'nunit',
+      });
       expect(res).not.toBeNull();
       expect(res).toMatchSnapshot();
       expect(res.sourceUrl).toBeDefined();
diff --git a/test/datasource/orb.spec.js b/test/datasource/orb.spec.js
index c36a3778ffd4648914e6228f9236fafa7d1ec6f9..b22988f41430c6617137878751929a1a970b5006 100644
--- a/test/datasource/orb.spec.js
+++ b/test/datasource/orb.spec.js
@@ -35,7 +35,8 @@ describe('datasource/orb', () => {
       got.mockReturnValueOnce({ body: {} });
       expect(
         await datasource.getPkgReleases({
-          purl: 'pkg:orb/hyper-expanse/library-release-workflows',
+          datasource: 'orb',
+          lookupName: 'hyper-expanse/library-release-workflows',
         })
       ).toBeNull();
     });
@@ -47,7 +48,8 @@ describe('datasource/orb', () => {
       );
       expect(
         await datasource.getPkgReleases({
-          purl: 'pkg:orb/hyper-expanse/library-release-workflows',
+          datasource: 'orb',
+          lookupName: 'hyper-expanse/library-release-workflows',
         })
       ).toBeNull();
     });
@@ -57,7 +59,8 @@ describe('datasource/orb', () => {
       });
       expect(
         await datasource.getPkgReleases({
-          purl: 'pkg:orb/hyper-expanse/library-release-workflows',
+          datasource: 'orb',
+          lookupName: 'hyper-expanse/library-release-workflows',
         })
       ).toBeNull();
     });
@@ -66,7 +69,8 @@ describe('datasource/orb', () => {
         body: orbData,
       });
       const res = await datasource.getPkgReleases({
-        purl: 'pkg:orb/hyper-expanse/library-release-workflows',
+        datasource: 'orb',
+        lookupName: 'hyper-expanse/library-release-workflows',
       });
       expect(res).toMatchSnapshot();
       expect(res).not.toBeNull();
@@ -77,7 +81,8 @@ describe('datasource/orb', () => {
         body: orbData,
       });
       const res = await datasource.getPkgReleases({
-        purl: 'pkg:orb/hyper-expanse/library-release-workflows',
+        datasource: 'orb',
+        lookupName: 'hyper-expanse/library-release-workflows',
       });
       expect(res).toMatchSnapshot();
       expect(res.homepage).toEqual('https://google.com');
diff --git a/test/datasource/packagist.spec.js b/test/datasource/packagist.spec.js
index 3ca94165faff4f85222a49db64c9cbff56195bf8..a9a34285ccd07496d38d2b785095d96393bbd662 100644
--- a/test/datasource/packagist.spec.js
+++ b/test/datasource/packagist.spec.js
@@ -20,6 +20,7 @@ describe('datasource/packagist', () => {
       hostRules.find = jest.fn(input => input);
       global.repoCache = {};
       config = {
+        datasource: 'packagist',
         versionScheme: 'composer',
         registryUrls: [
           {
@@ -32,6 +33,7 @@ describe('datasource/packagist', () => {
     });
     it('supports custom registries', async () => {
       config = {
+        datasource: 'packagist',
         registryUrls: [
           {
             type: 'composer',
@@ -59,7 +61,7 @@ describe('datasource/packagist', () => {
       };
       const res = await datasource.getPkgReleases({
         ...config,
-        purl: 'pkg:packagist/something/one',
+        lookupName: 'something/one',
       });
       expect(res).toBeNull();
     });
@@ -79,7 +81,7 @@ describe('datasource/packagist', () => {
       });
       const res = await datasource.getPkgReleases({
         ...config,
-        purl: 'pkg:packagist/vendor/package-name',
+        lookupName: 'vendor/package-name',
       });
       expect(res).toMatchSnapshot();
     });
@@ -91,7 +93,7 @@ describe('datasource/packagist', () => {
       );
       const res = await datasource.getPkgReleases({
         ...config,
-        purl: 'pkg:packagist/vendor/package-name',
+        lookupName: 'vendor/package-name',
       });
       expect(res).toBeNull();
     });
@@ -104,7 +106,7 @@ describe('datasource/packagist', () => {
       );
       const res = await datasource.getPkgReleases({
         ...config,
-        purl: 'pkg:packagist/drewm/mailchip-api',
+        lookupName: 'drewm/mailchip-api',
       });
       expect(res).toBeNull();
     });
@@ -129,7 +131,7 @@ describe('datasource/packagist', () => {
       });
       const res = await datasource.getPkgReleases({
         ...config,
-        purl: 'pkg:packagist/guzzlehttp/guzzle',
+        lookupName: 'guzzlehttp/guzzle',
       });
       expect(res).toMatchSnapshot();
       expect(res).not.toBeNull();
@@ -168,7 +170,7 @@ describe('datasource/packagist', () => {
       });
       const res = await datasource.getPkgReleases({
         ...config,
-        purl: 'pkg:packagist/wpackagist-plugin/1beyt',
+        lookupName: 'wpackagist-plugin/1beyt',
       });
       expect(res).toMatchSnapshot();
       expect(res).not.toBeNull();
@@ -207,7 +209,7 @@ describe('datasource/packagist', () => {
       });
       const res = await datasource.getPkgReleases({
         ...config,
-        purl: 'pkg:packagist/some/other',
+        lookupName: 'some/other',
       });
       expect(res).toBeNull();
     });
@@ -219,7 +221,7 @@ describe('datasource/packagist', () => {
       expect(
         await datasource.getPkgReleases({
           ...config,
-          purl: 'pkg:packagist/drewm/mailchimp-api',
+          lookupName: 'drewm/mailchimp-api',
         })
       ).toMatchSnapshot();
     });
diff --git a/test/datasource/pypi.spec.js b/test/datasource/pypi.spec.js
index f1174af3771eb76eaabe0fd8c60b3d16dfc2e4aa..d9cb78702a5d219f56480fcca02a20deea737812 100644
--- a/test/datasource/pypi.spec.js
+++ b/test/datasource/pypi.spec.js
@@ -27,7 +27,10 @@ describe('datasource/pypi', () => {
     it('returns null for empty result', async () => {
       got.mockReturnValueOnce({});
       expect(
-        await datasource.getPkgReleases({ purl: 'pkg:pypi/something' })
+        await datasource.getPkgReleases({
+          datasource: 'pypi',
+          lookupName: 'something',
+        })
       ).toBeNull();
     });
     it('returns null for 404', async () => {
@@ -35,7 +38,10 @@ describe('datasource/pypi', () => {
         throw new Error();
       });
       expect(
-        await datasource.getPkgReleases({ purl: 'pkg:pypi/something' })
+        await datasource.getPkgReleases({
+          datasource: 'pypi',
+          lookupName: 'something',
+        })
       ).toBeNull();
     });
     it('processes real data', async () => {
@@ -43,7 +49,10 @@ describe('datasource/pypi', () => {
         body: JSON.parse(res1),
       });
       expect(
-        await datasource.getPkgReleases({ purl: 'pkg:pypi/azure-cli-monitor' })
+        await datasource.getPkgReleases({
+          datasource: 'pypi',
+          lookupName: 'azure-cli-monitor',
+        })
       ).toMatchSnapshot();
     });
     it('supports custom datasource url', async () => {
@@ -55,7 +64,8 @@ describe('datasource/pypi', () => {
       };
       await datasource.getPkgReleases({
         ...config,
-        purl: 'pkg:pypi/azure-cli-monitor',
+        datasource: 'pypi',
+        lookupName: 'azure-cli-monitor',
       });
       expect(got.mock.calls).toMatchSnapshot();
     });
@@ -65,7 +75,10 @@ describe('datasource/pypi', () => {
       });
       const pipIndexUrl = process.env.PIP_INDEX_URL;
       process.env.PIP_INDEX_URL = 'https://my.pypi.python/pypi/';
-      await datasource.getPkgReleases({ purl: 'pkg:pypi/azure-cli-monitor' });
+      await datasource.getPkgReleases({
+        datasource: 'pypi',
+        lookupName: 'azure-cli-monitor',
+      });
       expect(got.mock.calls).toMatchSnapshot();
       process.env.PIP_INDEX_URL = pipIndexUrl;
     });
@@ -84,7 +97,8 @@ describe('datasource/pypi', () => {
       };
       await datasource.getPkgReleases({
         ...config,
-        purl: 'pkg:pypi/azure-cli-monitor',
+        datasource: 'pypi',
+        lookupName: 'azure-cli-monitor',
       });
       expect(got.mock.calls).toMatchSnapshot();
     });
@@ -98,7 +112,10 @@ describe('datasource/pypi', () => {
         },
       });
       expect(
-        await datasource.getPkgReleases({ purl: 'pkg:pypi/something' })
+        await datasource.getPkgReleases({
+          datasource: 'pypi',
+          lookupName: 'something',
+        })
       ).toMatchSnapshot();
     });
     it('returns null if mismatched name', async () => {
@@ -111,7 +128,10 @@ describe('datasource/pypi', () => {
         },
       });
       expect(
-        await datasource.getPkgReleases({ purl: 'pkg:pypi/something' })
+        await datasource.getPkgReleases({
+          datasource: 'pypi',
+          lookupName: 'something',
+        })
       ).toBeNull();
     });
 
@@ -135,7 +155,8 @@ describe('datasource/pypi', () => {
       expect(
         await datasource.getPkgReleases({
           compatibility: { python: '2.7' },
-          purl: 'pkg:pypi/doit',
+          datasource: 'pypi',
+          lookupName: 'doit',
         })
       ).toMatchSnapshot();
     });
diff --git a/test/datasource/rubygems/index.spec.js b/test/datasource/rubygems/index.spec.js
index 681b00418529e7a24666fcadba6674e777fb47b8..30a368e61776cf19079a44cffa7d77b63a08da38 100644
--- a/test/datasource/rubygems/index.spec.js
+++ b/test/datasource/rubygems/index.spec.js
@@ -9,9 +9,10 @@ describe('datasource/rubygems', () => {
   describe('getPkgReleases', () => {
     const SKIP_CACHE = process.env.RENOVATE_SKIP_CACHE;
 
-    const pkg = { lookupName: 'rails' };
-    const registryUrls = ['https://thirdparty.com', 'https://firstparty.com'];
-    const params = [pkg, { registryUrls }];
+    const params = {
+      lookupName: 'rails',
+      registryUrls: ['https://thirdparty.com', 'https://firstparty.com'],
+    };
 
     beforeEach(() => {
       process.env.RENOVATE_SKIP_CACHE = true;
@@ -20,7 +21,7 @@ describe('datasource/rubygems', () => {
 
     it('returns null for missing pkg', async () => {
       got.mockReturnValueOnce({});
-      expect(await rubygems.getPkgReleases(...params)).toBeNull();
+      expect(await rubygems.getPkgReleases(params)).toBeNull();
     });
 
     it('works with real data', async () => {
@@ -28,7 +29,7 @@ describe('datasource/rubygems', () => {
         .mockReturnValueOnce({ body: railsInfo })
         .mockReturnValueOnce({ body: railsVersions });
 
-      expect(await rubygems.getPkgReleases(...params)).toMatchSnapshot();
+      expect(await rubygems.getPkgReleases(params)).toMatchSnapshot();
     });
 
     it('uses multiple source urls', async () => {
@@ -41,12 +42,12 @@ describe('datasource/rubygems', () => {
         .mockImplementationOnce(() => ({ body: railsInfo }))
         .mockImplementationOnce(() => ({ body: railsVersions }));
 
-      expect(await rubygems.getPkgReleases(...params)).toMatchSnapshot();
+      expect(await rubygems.getPkgReleases(params)).toMatchSnapshot();
     });
 
     it('returns null if mismatched name', async () => {
       got.mockReturnValueOnce({ body: { ...railsInfo, name: 'oooops' } });
-      expect(await rubygems.getPkgReleases(...params)).toBeNull();
+      expect(await rubygems.getPkgReleases(params)).toBeNull();
     });
 
     afterEach(() => {
diff --git a/test/datasource/terraform.spec.js b/test/datasource/terraform.spec.js
index 5241a9e05fb9d214244962be8bd34976b49ff334..df3e13e697fce3a6b51969c529efe974d8a7f410 100644
--- a/test/datasource/terraform.spec.js
+++ b/test/datasource/terraform.spec.js
@@ -19,7 +19,8 @@ describe('datasource/terraform', () => {
       got.mockReturnValueOnce({ body: {} });
       expect(
         await datasource.getPkgReleases({
-          purl: 'pkg:terraform/hashicorp/consul/aws',
+          datasource: 'terraform',
+          lookupName: 'hashicorp/consul/aws',
         })
       ).toBeNull();
     });
@@ -31,7 +32,8 @@ describe('datasource/terraform', () => {
       );
       expect(
         await datasource.getPkgReleases({
-          purl: 'pkg:terraform/hashicorp/consul/aws',
+          datasource: 'terraform',
+          lookupName: 'hashicorp/consul/aws',
         })
       ).toBeNull();
     });
@@ -41,7 +43,8 @@ describe('datasource/terraform', () => {
       });
       expect(
         await datasource.getPkgReleases({
-          purl: 'pkg:terraform/hashicorp/consul/aws',
+          datasource: 'terraform',
+          lookupName: 'hashicorp/consul/aws',
         })
       ).toBeNull();
     });
@@ -50,7 +53,8 @@ describe('datasource/terraform', () => {
         body: JSON.parse(consulData),
       });
       const res = await datasource.getPkgReleases({
-        purl: 'pkg:terraform/hashicorp/consul/aws',
+        datasource: 'terraform',
+        lookupName: 'hashicorp/consul/aws',
       });
       expect(res).toMatchSnapshot();
       expect(res).not.toBeNull();
@@ -60,7 +64,8 @@ describe('datasource/terraform', () => {
         body: JSON.parse(consulData),
       });
       const res = await datasource.getPkgReleases({
-        purl: 'pkg:terraform/registry.terraform.io/hashicorp/consul/aws',
+        datasource: 'terraform',
+        lookupName: 'registry.terraform.io/hashicorp/consul/aws',
       });
       expect(res).toMatchSnapshot();
       expect(res).not.toBeNull();
@@ -70,7 +75,8 @@ describe('datasource/terraform', () => {
         body: JSON.parse(consulData),
       });
       const res = await datasource.getPkgReleases({
-        purl: 'pkg:terraform/consul/foo',
+        datasource: 'terraform',
+        lookupName: 'consul/foo',
         registryUrls: ['https://terraform.company.com'],
       });
       expect(res).toBeNull();
diff --git a/test/manager/ansible/__snapshots__/extract.spec.js.snap b/test/manager/ansible/__snapshots__/extract.spec.js.snap
index d3bc173b3703f7a6e879a209739ffe22a8162c98..9fff5627d90b267a19df8d11dde0634fd16d232f 100644
--- a/test/manager/ansible/__snapshots__/extract.spec.js.snap
+++ b/test/manager/ansible/__snapshots__/extract.spec.js.snap
@@ -7,9 +7,9 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "busybox",
     "currentValue": undefined,
+    "datasource": "docker",
     "depName": "busybox",
     "lineNumber": 4,
-    "purl": "pkg:docker/busybox",
     "versionScheme": "docker",
   },
   Object {
@@ -17,9 +17,9 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "redis",
     "currentValue": undefined,
+    "datasource": "docker",
     "depName": "redis",
     "lineNumber": 11,
-    "purl": "pkg:docker/redis",
     "versionScheme": "docker",
   },
   Object {
@@ -27,9 +27,9 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "someuser/appimage",
     "currentValue": undefined,
+    "datasource": "docker",
     "depName": "someuser/appimage",
     "lineNumber": 23,
-    "purl": "pkg:docker/someuser/appimage",
     "versionScheme": "docker",
   },
   Object {
@@ -37,9 +37,9 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "ubuntu:14.04",
     "currentValue": "14.04",
+    "datasource": "docker",
     "depName": "ubuntu",
     "lineNumber": 40,
-    "purl": "pkg:docker/ubuntu",
     "versionScheme": "docker",
   },
   Object {
@@ -47,9 +47,9 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "someuser/anotherappimage",
     "currentValue": undefined,
+    "datasource": "docker",
     "depName": "someuser/anotherappimage",
     "lineNumber": 52,
-    "purl": "pkg:docker/someuser/anotherappimage",
     "versionScheme": "docker",
   },
   Object {
@@ -57,9 +57,9 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "busybox",
     "currentValue": undefined,
+    "datasource": "docker",
     "depName": "busybox",
     "lineNumber": 64,
-    "purl": "pkg:docker/busybox",
     "versionScheme": "docker",
   },
   Object {
@@ -67,9 +67,9 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "postgres:latest",
     "currentValue": "latest",
+    "datasource": "docker",
     "depName": "postgres",
     "lineNumber": 76,
-    "purl": "pkg:docker/postgres",
     "versionScheme": "docker",
   },
   Object {
@@ -77,9 +77,9 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "ubuntu:14.04",
     "currentValue": "14.04",
+    "datasource": "docker",
     "depName": "ubuntu",
     "lineNumber": 83,
-    "purl": "pkg:docker/ubuntu",
     "versionScheme": "docker",
   },
   Object {
@@ -87,9 +87,9 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "ubuntu:14.04",
     "currentValue": "14.04",
+    "datasource": "docker",
     "depName": "ubuntu",
     "lineNumber": 96,
-    "purl": "pkg:docker/ubuntu",
     "versionScheme": "docker",
   },
 ]
@@ -102,9 +102,9 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "sameersbn/gitlab:11.5.1",
     "currentValue": "11.5.1",
+    "datasource": "docker",
     "depName": "sameersbn/gitlab",
     "lineNumber": 8,
-    "purl": "pkg:docker/sameersbn/gitlab",
     "versionScheme": "docker",
   },
   Object {
@@ -112,9 +112,9 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "sameersbn/postgresql:10",
     "currentValue": "10",
+    "datasource": "docker",
     "depName": "sameersbn/postgresql",
     "lineNumber": 30,
-    "purl": "pkg:docker/sameersbn/postgresql",
     "versionScheme": "docker",
   },
   Object {
@@ -122,9 +122,9 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "sameersbn/redis:4.0.9-1",
     "currentValue": "4.0.9-1",
+    "datasource": "docker",
     "depName": "sameersbn/redis",
     "lineNumber": 38,
-    "purl": "pkg:docker/sameersbn/redis",
     "versionScheme": "docker",
   },
   Object {
@@ -132,9 +132,9 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "registry:2.6.2",
     "currentValue": "2.6.2",
+    "datasource": "docker",
     "depName": "registry",
     "lineNumber": 43,
-    "purl": "pkg:docker/registry",
     "versionScheme": "docker",
   },
 ]
diff --git a/test/manager/bazel/__snapshots__/extract.spec.js.snap b/test/manager/bazel/__snapshots__/extract.spec.js.snap
index 514773788897c7a206569b7ce5347d557a083ed7..47ce0d4d388cdd8cf3897633620a344737c21f37 100644
--- a/test/manager/bazel/__snapshots__/extract.spec.js.snap
+++ b/test/manager/bazel/__snapshots__/extract.spec.js.snap
@@ -4,6 +4,7 @@ exports[`lib/manager/bazel/extract extractPackageFile() extracts multiple types
 Array [
   Object {
     "currentValue": "v1.0.5",
+    "datasource": "go",
     "def": "go_repository(
     name = \\"com_github_bitly_go-nsq\\",
     importpath = \\"github.com/bitly/go-nsq\\",
@@ -12,12 +13,13 @@ Array [
 ",
     "depName": "com_github_bitly_go-nsq",
     "depType": "go_repository",
-    "purl": "pkg:go/github.com/bitly/go-nsq",
+    "lookupName": "github.com/bitly/go-nsq",
   },
   Object {
     "currentDigest": "dec09d789f3dba190787f8b4454c7d3c936fed9e",
     "currentDigestShort": "dec09d7",
     "currentValue": "v0.0.0",
+    "datasource": "go",
     "def": "go_repository(
    name = \\"com_github_google_uuid\\",
    importpath = \\"github.com/google/uuid\\",
@@ -27,10 +29,11 @@ Array [
     "depName": "com_github_google_uuid",
     "depType": "go_repository",
     "digestOneAndOnly": true,
-    "purl": "pkg:go/github.com/google/uuid",
+    "lookupName": "github.com/google/uuid",
   },
   Object {
     "currentValue": "v2",
+    "datasource": "go",
     "def": "go_repository(
     name = \\"com_gopkgin_mgo_v2\\",
     importpath = \\"gopkg.in/mgo.v2\\",
@@ -39,10 +42,11 @@ Array [
 ",
     "depName": "com_gopkgin_mgo_v2",
     "depType": "go_repository",
-    "purl": "pkg:go/gopkg.in/mgo.v2",
+    "lookupName": "gopkg.in/mgo.v2",
   },
   Object {
     "currentValue": "0.3.1",
+    "datasource": "github",
     "def": "git_repository(
     name = \\"build_bazel_rules_nodejs\\",
     remote = \\"https://github.com/bazelbuild/rules_nodejs.git\\",
@@ -51,11 +55,12 @@ Array [
 ",
     "depName": "build_bazel_rules_nodejs",
     "depType": "git_repository",
-    "purl": "pkg:github/bazelbuild/rules_nodejs",
+    "lookupName": "bazelbuild/rules_nodejs",
     "remote": "https://github.com/bazelbuild/rules_nodejs.git",
   },
   Object {
     "currentValue": "0.6.1",
+    "datasource": "github",
     "def": "git_repository(
     name = \\"build_bazel_rules_typescript\\",
     remote = \\"https://github.com/bazelbuild/rules_typescript.git\\",
@@ -64,11 +69,12 @@ Array [
 ",
     "depName": "build_bazel_rules_typescript",
     "depType": "git_repository",
-    "purl": "pkg:github/bazelbuild/rules_typescript",
+    "lookupName": "bazelbuild/rules_typescript",
     "remote": "https://github.com/bazelbuild/rules_typescript.git",
   },
   Object {
     "currentValue": "0.0.3",
+    "datasource": "github",
     "def": "git_repository(
     name = \\"io_bazel_rules_sass\\",
     remote = \\"https://github.com/bazelbuild/rules_sass.git\\",
@@ -77,11 +83,12 @@ Array [
 ",
     "depName": "io_bazel_rules_sass",
     "depType": "git_repository",
-    "purl": "pkg:github/bazelbuild/rules_sass",
+    "lookupName": "bazelbuild/rules_sass",
     "remote": "https://github.com/bazelbuild/rules_sass.git",
   },
   Object {
     "currentValue": "0.7.1",
+    "datasource": "github",
     "def": "http_archive(
     name = \\"io_bazel_rules_go\\",
     url = \\"https://github.com/bazelbuild/rules_go/releases/download/0.7.1/rules_go-0.7.1.tar.gz\\",
@@ -90,11 +97,13 @@ Array [
 ",
     "depName": "io_bazel_rules_go",
     "depType": "http_archive",
-    "purl": "pkg:github/bazelbuild/rules_go#releases",
+    "lookupName": "bazelbuild/rules_go",
+    "lookupType": "releases",
     "repo": "bazelbuild/rules_go",
   },
   Object {
     "currentValue": "0.5.0",
+    "datasource": "github",
     "def": "http_archive(
     name = \\"bazel_skylib\\",
     sha256 = \\"b5f6abe419da897b7901f90cbab08af958b97a8f3575b0d3dd062ac7ce78541f\\",
@@ -107,7 +116,8 @@ Array [
 ",
     "depName": "bazel_skylib",
     "depType": "http_archive",
-    "purl": "pkg:github/bazelbuild/bazel-skylib#releases",
+    "lookupName": "bazelbuild/bazel-skylib",
+    "lookupType": "releases",
     "repo": "bazelbuild/bazel-skylib",
   },
 ]
diff --git a/test/manager/bazel/extract.spec.js b/test/manager/bazel/extract.spec.js
index b66f0a3d0d826879990b0c240ea794d25bcb2114..c785b9d9c481216fff390aef3b43b86f0116f793 100644
--- a/test/manager/bazel/extract.spec.js
+++ b/test/manager/bazel/extract.spec.js
@@ -36,9 +36,8 @@ go_repository(
         `,
         config
       );
-      expect(successStory.deps[0].purl).toBe(
-        'pkg:go/github.com/test/uuid-fork'
-      );
+      expect(successStory.deps[0].datasource).toBe('go');
+      expect(successStory.deps[0].lookupName).toBe('github.com/test/uuid-fork');
 
       const badStory = extractPackageFile(
         `
diff --git a/test/manager/buildkite/__snapshots__/extract.spec.js.snap b/test/manager/buildkite/__snapshots__/extract.spec.js.snap
index 18b6d27e347a2c082fc311c97ccc83e2f7636fd5..cc4e1f4a9fdbfdb95b93e9af7c61640a7c7119a2 100644
--- a/test/manager/buildkite/__snapshots__/extract.spec.js.snap
+++ b/test/manager/buildkite/__snapshots__/extract.spec.js.snap
@@ -6,21 +6,18 @@ Array [
     "currentValue": "v1.3.2.5",
     "depName": "namespace/docker-compose",
     "lineNumber": 4,
-    "purl": undefined,
     "skipReason": "invalid-version",
   },
   Object {
     "currentValue": "v1.3.2",
     "depName": "https://github.com/buildkite/plugin-docker-compose",
     "lineNumber": 15,
-    "purl": undefined,
     "skipReason": "git-plugin",
   },
   Object {
     "currentValue": "v1.3.2",
     "depName": "github.com/buildkite/plugin-docker-compose",
     "lineNumber": 22,
-    "purl": undefined,
     "skipReason": "unknown",
   },
 ]
@@ -30,16 +27,18 @@ exports[`lib/manager/buildkite/extract extractPackageFile() extracts arrays of p
 Array [
   Object {
     "currentValue": "v2.0.1",
+    "datasource": "github",
     "depName": "docker-login",
     "lineNumber": 2,
-    "purl": "pkg:github/buildkite-plugins/docker-login-buildkite-plugin",
+    "lookupName": "buildkite-plugins/docker-login-buildkite-plugin",
     "skipReason": undefined,
   },
   Object {
     "currentValue": "v2.0.1",
+    "datasource": "github",
     "depName": "docker-login",
     "lineNumber": 10,
-    "purl": "pkg:github/buildkite-plugins/docker-login-buildkite-plugin",
+    "lookupName": "buildkite-plugins/docker-login-buildkite-plugin",
     "skipReason": undefined,
   },
 ]
@@ -49,16 +48,18 @@ exports[`lib/manager/buildkite/extract extractPackageFile() extracts multiple pl
 Array [
   Object {
     "currentValue": "v1.3.2",
+    "datasource": "github",
     "depName": "docker-compose",
     "lineNumber": 4,
-    "purl": "pkg:github/buildkite-plugins/docker-compose-buildkite-plugin",
+    "lookupName": "buildkite-plugins/docker-compose-buildkite-plugin",
     "skipReason": undefined,
   },
   Object {
     "currentValue": "v1.3.2",
+    "datasource": "github",
     "depName": "docker-compose",
     "lineNumber": 15,
-    "purl": "pkg:github/buildkite-plugins/docker-compose-buildkite-plugin",
+    "lookupName": "buildkite-plugins/docker-compose-buildkite-plugin",
     "skipReason": undefined,
   },
 ]
@@ -68,9 +69,10 @@ exports[`lib/manager/buildkite/extract extractPackageFile() extracts simple sing
 Array [
   Object {
     "currentValue": "v2.0.0",
+    "datasource": "github",
     "depName": "abc/detect-clowns",
     "lineNumber": 2,
-    "purl": "pkg:github/abc/detect-clowns-buildkite-plugin",
+    "lookupName": "abc/detect-clowns-buildkite-plugin",
     "skipReason": undefined,
   },
 ]
diff --git a/test/manager/bundler/__snapshots__/extract.spec.js.snap b/test/manager/bundler/__snapshots__/extract.spec.js.snap
index e12c84b5f2f3fe73b84fb5cca7f66f8bc79ea748..1b9ea9738fb4e24c28135e5d1e7ba1adfc52ca9f 100644
--- a/test/manager/bundler/__snapshots__/extract.spec.js.snap
+++ b/test/manager/bundler/__snapshots__/extract.spec.js.snap
@@ -8,21 +8,21 @@ Object {
   "deps": Array [
     Object {
       "currentValue": ">= 11.1",
+      "datasource": "rubygems",
       "depName": "rake",
       "lineNumber": 9,
-      "purl": "pkg:rubygems/rake",
     },
     Object {
       "currentValue": ">= 2.15",
+      "datasource": "rubygems",
       "depName": "capybara",
       "lineNumber": 11,
-      "purl": "pkg:rubygems/capybara",
     },
     Object {
       "currentValue": "~> 1.2",
+      "datasource": "rubygems",
       "depName": "rack-cache",
       "lineNumber": 13,
-      "purl": "pkg:rubygems/rack-cache",
     },
     Object {
       "depName": "sass-rails",
@@ -31,9 +31,9 @@ Object {
     },
     Object {
       "currentValue": "~> 5",
+      "datasource": "rubygems",
       "depName": "turbolinks",
       "lineNumber": 15,
-      "purl": "pkg:rubygems/turbolinks",
     },
     Object {
       "depName": "webpacker",
@@ -42,45 +42,45 @@ Object {
     },
     Object {
       "currentValue": "~> 3.1.11",
+      "datasource": "rubygems",
       "depName": "bcrypt",
       "lineNumber": 20,
-      "purl": "pkg:rubygems/bcrypt",
     },
     Object {
       "currentValue": ">= 1.3.0",
+      "datasource": "rubygems",
       "depName": "uglifier",
       "lineNumber": 24,
-      "purl": "pkg:rubygems/uglifier",
     },
     Object {
       "currentValue": ">= 2.0.0",
+      "datasource": "rubygems",
       "depName": "json",
       "lineNumber": 27,
-      "purl": "pkg:rubygems/json",
     },
     Object {
       "currentValue": ">= 0.47",
+      "datasource": "rubygems",
       "depName": "rubocop",
       "lineNumber": 29,
-      "purl": "pkg:rubygems/rubocop",
     },
     Object {
       "currentValue": "~> 1.0",
+      "datasource": "rubygems",
       "depName": "sdoc",
       "depTypes": Array [
         "doc",
       ],
       "lineNumber": 32,
-      "purl": "pkg:rubygems/sdoc",
     },
     Object {
       "currentValue": "~> 3.2.3",
+      "datasource": "rubygems",
       "depName": "redcarpet",
       "depTypes": Array [
         "doc",
       ],
       "lineNumber": 33,
-      "purl": "pkg:rubygems/redcarpet",
     },
     Object {
       "depName": "w3c_validators",
@@ -92,12 +92,12 @@ Object {
     },
     Object {
       "currentValue": "~> 1.2.0",
+      "datasource": "rubygems",
       "depName": "kindlerb",
       "depTypes": Array [
         "doc",
       ],
       "lineNumber": 35,
-      "purl": "pkg:rubygems/kindlerb",
     },
     Object {
       "depName": "dalli",
@@ -106,9 +106,9 @@ Object {
     },
     Object {
       "currentValue": ">= 3.0.5, < 3.2",
+      "datasource": "rubygems",
       "depName": "listen",
       "lineNumber": 40,
-      "purl": "pkg:rubygems/listen",
     },
     Object {
       "depName": "libxml-ruby",
@@ -122,9 +122,9 @@ Object {
     },
     Object {
       "currentValue": ">= 1.1.0",
+      "datasource": "rubygems",
       "depName": "bootsnap",
       "lineNumber": 45,
-      "purl": "pkg:rubygems/bootsnap",
     },
     Object {
       "depName": "resque",
@@ -232,12 +232,12 @@ Object {
     },
     Object {
       "currentValue": "~> 4.0",
+      "datasource": "rubygems",
       "depName": "redis",
       "depTypes": Array [
         "cable",
       ],
       "lineNumber": 67,
-      "purl": "pkg:rubygems/redis",
     },
     Object {
       "depName": "redis-namespace",
@@ -289,12 +289,12 @@ Object {
     },
     Object {
       "currentValue": "~> 1.11",
+      "datasource": "rubygems",
       "depName": "google-cloud-storage",
       "depTypes": Array [
         "storage",
       ],
       "lineNumber": 81,
-      "purl": "pkg:rubygems/google-cloud-storage",
     },
     Object {
       "depName": "azure-storage",
@@ -306,12 +306,12 @@ Object {
     },
     Object {
       "currentValue": "~> 1.2",
+      "datasource": "rubygems",
       "depName": "image_processing",
       "depTypes": Array [
         "storage",
       ],
       "lineNumber": 84,
-      "purl": "pkg:rubygems/image_processing",
     },
     Object {
       "depName": "aws-sdk-sns",
@@ -381,39 +381,39 @@ Object {
     },
     Object {
       "currentValue": ">= 1.8.1",
+      "datasource": "rubygems",
       "depName": "nokogiri",
       "lineNumber": 113,
-      "purl": "pkg:rubygems/nokogiri",
     },
     Object {
       "currentValue": ">=1.4.6",
+      "datasource": "rubygems",
       "depName": "racc",
       "lineNumber": 116,
-      "purl": "pkg:rubygems/racc",
     },
     Object {
       "currentValue": "~> 1.3.6",
+      "datasource": "rubygems",
       "depName": "sqlite3",
       "lineNumber": 119,
-      "purl": "pkg:rubygems/sqlite3",
     },
     Object {
       "currentValue": ">= 0.18.0",
+      "datasource": "rubygems",
       "depName": "pg",
       "depTypes": Array [
         "db",
       ],
       "lineNumber": 122,
-      "purl": "pkg:rubygems/pg",
     },
     Object {
       "currentValue": ">= 0.4.10",
+      "datasource": "rubygems",
       "depName": "mysql2",
       "depTypes": Array [
         "db",
       ],
       "lineNumber": 123,
-      "purl": "pkg:rubygems/mysql2",
     },
     Object {
       "depName": "activerecord-jdbcsqlite3-adapter",
@@ -438,39 +438,39 @@ Object {
     },
     Object {
       "currentValue": ">= 1.3.0",
+      "datasource": "rubygems",
       "depName": "activerecord-jdbcsqlite3-adapter",
       "lineNumber": 135,
-      "purl": "pkg:rubygems/activerecord-jdbcsqlite3-adapter",
     },
     Object {
       "currentValue": ">= 1.3.0",
+      "datasource": "rubygems",
       "depName": "activerecord-jdbcmysql-adapter",
       "depTypes": Array [
         "db",
       ],
       "lineNumber": 137,
-      "purl": "pkg:rubygems/activerecord-jdbcmysql-adapter",
     },
     Object {
       "currentValue": ">= 1.3.0",
+      "datasource": "rubygems",
       "depName": "activerecord-jdbcpostgresql-adapter",
       "depTypes": Array [
         "db",
       ],
       "lineNumber": 138,
-      "purl": "pkg:rubygems/activerecord-jdbcpostgresql-adapter",
     },
     Object {
       "currentValue": "~> 3.0",
+      "datasource": "rubygems",
       "depName": "psych",
       "lineNumber": 146,
-      "purl": "pkg:rubygems/psych",
     },
     Object {
       "currentValue": "~> 2.2",
+      "datasource": "rubygems",
       "depName": "ruby-oci8",
       "lineNumber": 152,
-      "purl": "pkg:rubygems/ruby-oci8",
     },
     Object {
       "depName": "activerecord-oracle_enhanced-adapter",
@@ -489,9 +489,9 @@ Object {
     },
     Object {
       "currentValue": ">= 0.1.0",
+      "datasource": "rubygems",
       "depName": "wdm",
       "lineNumber": 160,
-      "purl": "pkg:rubygems/wdm",
     },
   ],
   "registryUrls": Array [
diff --git a/test/manager/circleci/__snapshots__/extract.spec.js.snap b/test/manager/circleci/__snapshots__/extract.spec.js.snap
index 0be6eee2e1bffa236035072521ee50cef8aa1112..676008d5ef5a605989991c91c7bab676dc3bd550 100644
--- a/test/manager/circleci/__snapshots__/extract.spec.js.snap
+++ b/test/manager/circleci/__snapshots__/extract.spec.js.snap
@@ -8,10 +8,10 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "node",
     "currentValue": undefined,
+    "datasource": "docker",
     "depName": "node",
     "depType": "docker",
     "lineNumber": 12,
-    "purl": "pkg:docker/node",
   },
   Object {
     "commitMessageTopic": "Node.js",
@@ -19,10 +19,10 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "node:4",
     "currentValue": "4",
+    "datasource": "docker",
     "depName": "node",
     "depType": "docker",
     "lineNumber": 57,
-    "purl": "pkg:docker/node",
   },
   Object {
     "commitMessageTopic": "Node.js",
@@ -30,10 +30,10 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "node:6",
     "currentValue": "6",
+    "datasource": "docker",
     "depName": "node",
     "depType": "docker",
     "lineNumber": 61,
-    "purl": "pkg:docker/node",
   },
   Object {
     "commitMessageTopic": "Node.js",
@@ -41,10 +41,10 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "node:8.9.0",
     "currentValue": "8.9.0",
+    "datasource": "docker",
     "depName": "node",
     "depType": "docker",
     "lineNumber": 65,
-    "purl": "pkg:docker/node",
   },
 ]
 `;
@@ -54,30 +54,33 @@ Array [
   Object {
     "commitMessageTopic": "{{{depName}}} orb",
     "currentValue": "4.1.0",
+    "datasource": "orb",
     "depName": "release-workflows",
     "depType": "orb",
     "lineNumber": 3,
-    "purl": "pkg:orb/hutson/library-release-workflows",
+    "lookupName": "hutson/library-release-workflows",
     "rangeStrategy": "pin",
     "versionScheme": "npm",
   },
   Object {
     "commitMessageTopic": "{{{depName}}} orb",
     "currentValue": undefined,
+    "datasource": "orb",
     "depName": "no-version",
     "depType": "orb",
     "lineNumber": 4,
-    "purl": "pkg:orb/abc/def",
+    "lookupName": "abc/def",
     "rangeStrategy": "pin",
     "versionScheme": "npm",
   },
   Object {
     "commitMessageTopic": "{{{depName}}} orb",
     "currentValue": "volatile",
+    "datasource": "orb",
     "depName": "volatile",
     "depType": "orb",
     "lineNumber": 5,
-    "purl": "pkg:orb/zzz/zzz",
+    "lookupName": "zzz/zzz",
     "rangeStrategy": "pin",
     "versionScheme": "npm",
   },
@@ -86,60 +89,60 @@ Array [
     "currentDigest": "sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
     "currentFrom": "python:3.7@sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
     "currentValue": "3.7",
+    "datasource": "docker",
     "depName": "python",
     "depType": "docker",
     "lineNumber": 20,
-    "purl": "pkg:docker/python",
   },
   Object {
     "currentDepTag": "python:3.7",
     "currentDigest": "sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
     "currentFrom": "python:3.7@sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
     "currentValue": "3.7",
+    "datasource": "docker",
     "depName": "python",
     "depType": "docker",
     "lineNumber": 27,
-    "purl": "pkg:docker/python",
   },
   Object {
     "currentDepTag": "python:3.7",
     "currentDigest": "sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
     "currentFrom": "python:3.7@sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
     "currentValue": "3.7",
+    "datasource": "docker",
     "depName": "python",
     "depType": "docker",
     "lineNumber": 34,
-    "purl": "pkg:docker/python",
   },
   Object {
     "currentDepTag": "python:3.7",
     "currentDigest": "sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
     "currentFrom": "python:3.7@sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
     "currentValue": "3.7",
+    "datasource": "docker",
     "depName": "python",
     "depType": "docker",
     "lineNumber": 41,
-    "purl": "pkg:docker/python",
   },
   Object {
     "currentDepTag": "pypy:3-6",
     "currentDigest": "sha256:eb6325b75c1c70b4992eaa1bdd29e24e5f14d5324b4714a49f3e67783473214b",
     "currentFrom": "pypy:3-6@sha256:eb6325b75c1c70b4992eaa1bdd29e24e5f14d5324b4714a49f3e67783473214b",
     "currentValue": "3-6",
+    "datasource": "docker",
     "depName": "pypy",
     "depType": "docker",
     "lineNumber": 50,
-    "purl": "pkg:docker/pypy",
   },
   Object {
     "currentDepTag": "python:3.7",
     "currentDigest": "sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
     "currentFrom": "python:3.7@sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
     "currentValue": "3.7",
+    "datasource": "docker",
     "depName": "python",
     "depType": "docker",
     "lineNumber": 57,
-    "purl": "pkg:docker/python",
   },
 ]
 `;
diff --git a/test/manager/composer/__snapshots__/extract.spec.js.snap b/test/manager/composer/__snapshots__/extract.spec.js.snap
index ef8560352dcea34da21dc29b92bade0b7aeb645e..b944859152b0797ff896853052d3e705ed62af8c 100644
--- a/test/manager/composer/__snapshots__/extract.spec.js.snap
+++ b/test/manager/composer/__snapshots__/extract.spec.js.snap
@@ -6,213 +6,213 @@ Object {
   "deps": Array [
     Object {
       "currentValue": ">=5.3.2",
+      "datasource": "packagist",
       "depName": "php",
       "depType": "require",
-      "purl": "pkg:packagist/php",
       "skipReason": "unsupported",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "symfony/assetic-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/symfony/assetic-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "symfony/monolog-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/symfony/monolog-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "symfony/swiftmailer-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/symfony/swiftmailer-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "2.1.*",
+      "datasource": "packagist",
       "depName": "symfony/symfony",
       "depType": "require",
-      "purl": "pkg:packagist/symfony/symfony",
     },
     Object {
       "currentValue": "2.2.2",
+      "datasource": "packagist",
       "depName": "doctrine/common",
       "depType": "require",
-      "purl": "pkg:packagist/doctrine/common",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "doctrine/doctrine-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/doctrine/doctrine-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "doctrine/doctrine-fixtures-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/doctrine/doctrine-fixtures-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "2.2.x-dev",
+      "datasource": "packagist",
       "depName": "doctrine/orm",
       "depType": "require",
-      "purl": "pkg:packagist/doctrine/orm",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "exercise/elastica-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/exercise/elastica-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "friendsofsymfony/rest-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/friendsofsymfony/rest-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "friendsofsymfony/user-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/friendsofsymfony/user-bundle",
       "skipReason": "any-version",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "fzaninotto/faker",
       "depType": "require",
-      "purl": "pkg:packagist/fzaninotto/faker",
       "skipReason": "any-version",
     },
     Object {
       "currentValue": "1.0.1",
+      "datasource": "packagist",
       "depName": "jms/di-extra-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/jms/di-extra-bundle",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "jms/payment-core-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/jms/payment-core-bundle",
       "skipReason": "any-version",
     },
     Object {
       "currentValue": "1.1.0",
+      "datasource": "packagist",
       "depName": "jms/security-extra-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/jms/security-extra-bundle",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "knplabs/knp-menu-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/knplabs/knp-menu-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "knplabs/knp-paginator-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/knplabs/knp-paginator-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "liip/imagine-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/liip/imagine-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "merk/dough-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/merk/dough-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "sensio/distribution-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/sensio/distribution-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "sensio/framework-extra-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/sensio/framework-extra-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "sensio/generator-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/sensio/generator-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "simplethings/entity-audit-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/simplethings/entity-audit-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "stof/doctrine-extensions-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/stof/doctrine-extensions-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "twig/extensions",
       "depType": "require",
-      "purl": "pkg:packagist/twig/extensions",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "2.3.*",
+      "datasource": "packagist",
       "depName": "behat/behat",
       "depType": "require-dev",
-      "purl": "pkg:packagist/behat/behat",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "behat/behat-bundle",
       "depType": "require-dev",
-      "purl": "pkg:packagist/behat/behat-bundle",
       "skipReason": "any-version",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "behat/mink-bundle",
       "depType": "require-dev",
-      "purl": "pkg:packagist/behat/mink-bundle",
       "skipReason": "any-version",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "behat/sahi-client",
       "depType": "require-dev",
-      "purl": "pkg:packagist/behat/sahi-client",
       "skipReason": "any-version",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "behat/common-contexts",
       "depType": "require-dev",
-      "purl": "pkg:packagist/behat/common-contexts",
       "skipReason": "any-version",
     },
   ],
@@ -225,213 +225,213 @@ Object {
   "deps": Array [
     Object {
       "currentValue": ">=5.3.2",
+      "datasource": "packagist",
       "depName": "php",
       "depType": "require",
-      "purl": "pkg:packagist/php",
       "skipReason": "unsupported",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "symfony/assetic-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/symfony/assetic-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "symfony/monolog-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/symfony/monolog-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "symfony/swiftmailer-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/symfony/swiftmailer-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "2.1.*",
+      "datasource": "packagist",
       "depName": "symfony/symfony",
       "depType": "require",
-      "purl": "pkg:packagist/symfony/symfony",
     },
     Object {
       "currentValue": "2.2.2",
+      "datasource": "packagist",
       "depName": "doctrine/common",
       "depType": "require",
-      "purl": "pkg:packagist/doctrine/common",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "doctrine/doctrine-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/doctrine/doctrine-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "doctrine/doctrine-fixtures-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/doctrine/doctrine-fixtures-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "2.2.x-dev",
+      "datasource": "packagist",
       "depName": "doctrine/orm",
       "depType": "require",
-      "purl": "pkg:packagist/doctrine/orm",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "exercise/elastica-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/exercise/elastica-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "friendsofsymfony/rest-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/friendsofsymfony/rest-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "friendsofsymfony/user-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/friendsofsymfony/user-bundle",
       "skipReason": "any-version",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "fzaninotto/faker",
       "depType": "require",
-      "purl": "pkg:packagist/fzaninotto/faker",
       "skipReason": "any-version",
     },
     Object {
       "currentValue": "1.0.1",
+      "datasource": "packagist",
       "depName": "jms/di-extra-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/jms/di-extra-bundle",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "jms/payment-core-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/jms/payment-core-bundle",
       "skipReason": "any-version",
     },
     Object {
       "currentValue": "1.1.0",
+      "datasource": "packagist",
       "depName": "jms/security-extra-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/jms/security-extra-bundle",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "knplabs/knp-menu-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/knplabs/knp-menu-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "knplabs/knp-paginator-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/knplabs/knp-paginator-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "liip/imagine-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/liip/imagine-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "merk/dough-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/merk/dough-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "sensio/distribution-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/sensio/distribution-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "sensio/framework-extra-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/sensio/framework-extra-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "sensio/generator-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/sensio/generator-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "simplethings/entity-audit-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/simplethings/entity-audit-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "stof/doctrine-extensions-bundle",
       "depType": "require",
-      "purl": "pkg:packagist/stof/doctrine-extensions-bundle",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "dev-master",
+      "datasource": "packagist",
       "depName": "twig/extensions",
       "depType": "require",
-      "purl": "pkg:packagist/twig/extensions",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": "2.3.*",
+      "datasource": "packagist",
       "depName": "behat/behat",
       "depType": "require-dev",
-      "purl": "pkg:packagist/behat/behat",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "behat/behat-bundle",
       "depType": "require-dev",
-      "purl": "pkg:packagist/behat/behat-bundle",
       "skipReason": "any-version",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "behat/mink-bundle",
       "depType": "require-dev",
-      "purl": "pkg:packagist/behat/mink-bundle",
       "skipReason": "any-version",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "behat/sahi-client",
       "depType": "require-dev",
-      "purl": "pkg:packagist/behat/sahi-client",
       "skipReason": "any-version",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "behat/common-contexts",
       "depType": "require-dev",
-      "purl": "pkg:packagist/behat/common-contexts",
       "skipReason": "any-version",
     },
   ],
@@ -445,90 +445,90 @@ Object {
   "deps": Array [
     Object {
       "currentValue": ">=5.5",
+      "datasource": "packagist",
       "depName": "php",
       "depType": "require",
-      "purl": "pkg:packagist/php",
       "skipReason": "unsupported",
     },
     Object {
       "currentValue": "~1.0.12",
+      "datasource": "packagist",
       "depName": "composer/installers",
       "depType": "require",
-      "purl": "pkg:packagist/composer/installers",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "johnpbloch/wordpress",
       "depType": "require",
-      "purl": "pkg:packagist/johnpbloch/wordpress",
       "skipReason": "any-version",
     },
     Object {
       "currentValue": "^2.0.1",
+      "datasource": "packagist",
       "depName": "vlucas/phpdotenv",
       "depType": "require",
-      "purl": "pkg:packagist/vlucas/phpdotenv",
     },
     Object {
       "currentValue": "^1.0",
+      "datasource": "packagist",
       "depName": "oscarotero/env",
       "depType": "require",
-      "purl": "pkg:packagist/oscarotero/env",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "wpackagist-plugin/tinymce-advanced",
       "depType": "require",
-      "purl": "pkg:packagist/wpackagist-plugin/tinymce-advanced",
       "skipReason": "any-version",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "wpackagist-plugin/acf-content-analysis-for-yoast-seo",
       "depType": "require",
-      "purl": "pkg:packagist/wpackagist-plugin/acf-content-analysis-for-yoast-seo",
       "skipReason": "any-version",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "wpackagist-plugin/duplicate-post",
       "depType": "require",
-      "purl": "pkg:packagist/wpackagist-plugin/duplicate-post",
       "skipReason": "any-version",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "wpackagist-plugin/simple-image-sizes",
       "depType": "require",
-      "purl": "pkg:packagist/wpackagist-plugin/simple-image-sizes",
       "skipReason": "any-version",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "wpackagist-plugin/wordpress-seo",
       "depType": "require",
-      "purl": "pkg:packagist/wpackagist-plugin/wordpress-seo",
       "skipReason": "any-version",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "wpackagist-plugin/timber-library",
       "depType": "require",
-      "purl": "pkg:packagist/wpackagist-plugin/timber-library",
       "skipReason": "any-version",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "wp-sync-db/wp-sync-db",
       "depType": "require",
-      "purl": "pkg:packagist/wp-sync-db/wp-sync-db",
       "skipReason": "any-version",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "asha23/wp-seed-timber",
       "depType": "require",
-      "purl": "pkg:packagist/asha23/wp-seed-timber",
       "skipReason": "any-version",
     },
   ],
@@ -571,29 +571,29 @@ Object {
   "deps": Array [
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "aws/aws-sdk-php",
       "depType": "require",
-      "purl": "pkg:packagist/aws/aws-sdk-php",
       "skipReason": "any-version",
     },
     Object {
       "currentValue": "dev-trunk",
+      "datasource": "packagist",
       "depName": "wpackagist-plugin/akismet",
       "depType": "require",
-      "purl": "pkg:packagist/wpackagist-plugin/akismet",
       "skipReason": "unsupported-constraint",
     },
     Object {
       "currentValue": ">=7.0.2",
+      "datasource": "packagist",
       "depName": "wpackagist-plugin/wordpress-seo",
       "depType": "require",
-      "purl": "pkg:packagist/wpackagist-plugin/wordpress-seo",
     },
     Object {
       "currentValue": "*",
+      "datasource": "packagist",
       "depName": "wpackagist-theme/hueman",
       "depType": "require",
-      "purl": "pkg:packagist/wpackagist-theme/hueman",
       "skipReason": "any-version",
     },
   ],
diff --git a/test/manager/docker-compose/__snapshots__/extract.spec.js.snap b/test/manager/docker-compose/__snapshots__/extract.spec.js.snap
index 156383802ab5563748eac4c22f3561d00f2beac7..af4857b5adab742ff7ca7f55520f1366267106f1 100644
--- a/test/manager/docker-compose/__snapshots__/extract.spec.js.snap
+++ b/test/manager/docker-compose/__snapshots__/extract.spec.js.snap
@@ -7,9 +7,9 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "quay.io/something/redis:alpine",
     "currentValue": "alpine",
+    "datasource": "docker",
     "depName": "quay.io/something/redis",
     "lineNumber": 4,
-    "purl": "pkg:docker/quay.io/something/redis",
   },
   Object {
     "commitMessageTopic": "Node.js",
@@ -17,59 +17,59 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "node:10.0.0",
     "currentValue": "10.0.0",
+    "datasource": "docker",
     "depName": "node",
     "lineNumber": 18,
-    "purl": "pkg:docker/node",
   },
   Object {
     "currentDepTag": "postgres:9.4.0",
     "currentDigest": undefined,
     "currentFrom": "postgres:9.4.0",
     "currentValue": "9.4.0",
+    "datasource": "docker",
     "depName": "postgres",
     "lineNumber": 21,
-    "purl": "pkg:docker/postgres",
   },
   Object {
     "currentDepTag": "dockersamples/examplevotingapp_vote:before",
     "currentDigest": undefined,
     "currentFrom": "dockersamples/examplevotingapp_vote:before",
     "currentValue": "before",
+    "datasource": "docker",
     "depName": "dockersamples/examplevotingapp_vote",
     "lineNumber": 31,
-    "purl": "pkg:docker/dockersamples/examplevotingapp_vote",
   },
   Object {
     "currentDepTag": "dockersamples/examplevotingapp_result:before",
     "currentDigest": undefined,
     "currentFrom": "dockersamples/examplevotingapp_result:before",
     "currentValue": "before",
+    "datasource": "docker",
     "depName": "dockersamples/examplevotingapp_result",
     "lineNumber": 46,
-    "purl": "pkg:docker/dockersamples/examplevotingapp_result",
   },
   Object {
     "currentDepTag": "dockersamples/examplevotingapp_worker",
     "currentDigest": undefined,
     "currentFrom": "dockersamples/examplevotingapp_worker",
     "currentValue": undefined,
+    "datasource": "docker",
     "depName": "dockersamples/examplevotingapp_worker",
     "lineNumber": 62,
-    "purl": "pkg:docker/dockersamples/examplevotingapp_worker",
   },
   Object {
     "currentDepTag": "dockersamples/visualizer:stable",
     "currentDigest": undefined,
     "currentFrom": "dockersamples/visualizer:stable",
     "currentValue": "stable",
+    "datasource": "docker",
     "depName": "dockersamples/visualizer",
     "lineNumber": 79,
-    "purl": "pkg:docker/dockersamples/visualizer",
   },
   Object {
     "currentFrom": "\${IMAGE:-synkodevelopers/edplugins}:\${TAG:-latest}",
+    "datasource": "docker",
     "lineNumber": 90,
-    "purl": "pkg:docker/undefined",
     "skipReason": "contains-variable",
   },
 ]
diff --git a/test/manager/dockerfile/__snapshots__/extract.spec.js.snap b/test/manager/dockerfile/__snapshots__/extract.spec.js.snap
index 02ff907d545a51199c7e3052ade417f0cf3d3d43..0288af7c1a665221023ac87a61d8062c45516630 100644
--- a/test/manager/dockerfile/__snapshots__/extract.spec.js.snap
+++ b/test/manager/dockerfile/__snapshots__/extract.spec.js.snap
@@ -8,22 +8,22 @@ Array [
     "currentDigest": "sha256:d743b4141b02fcfb8beb68f92b4cd164f60ee457bf2d053f36785bf86de16b0d",
     "currentFrom": "node:8.11.3-alpine@sha256:d743b4141b02fcfb8beb68f92b4cd164f60ee457bf2d053f36785bf86de16b0d",
     "currentValue": "8.11.3-alpine",
+    "datasource": "docker",
     "depName": "node",
     "fromPrefix": "FROM",
     "fromSuffix": "AS node",
     "lineNumber": 2,
-    "purl": "pkg:docker/node",
   },
   Object {
     "currentDepTag": "buildkite/puppeteer:1.1.1",
     "currentDigest": undefined,
     "currentFrom": "buildkite/puppeteer:1.1.1",
     "currentValue": "1.1.1",
+    "datasource": "docker",
     "depName": "buildkite/puppeteer",
     "fromPrefix": "FROM",
     "fromSuffix": "AS puppeteer",
     "lineNumber": 3,
-    "purl": "pkg:docker/buildkite/puppeteer",
   },
 ]
 `;
@@ -36,22 +36,22 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "node:6.12.3",
     "currentValue": "6.12.3",
+    "datasource": "docker",
     "depName": "node",
     "fromPrefix": "FROM",
     "fromSuffix": "as frontend",
     "lineNumber": 0,
-    "purl": "pkg:docker/node",
   },
   Object {
     "currentDepTag": "python:3.6-slim",
     "currentDigest": undefined,
     "currentFrom": "python:3.6-slim",
     "currentValue": "3.6-slim",
+    "datasource": "docker",
     "depName": "python",
     "fromPrefix": "FROM",
     "fromSuffix": "",
     "lineNumber": 4,
-    "purl": "pkg:docker/python",
   },
 ]
 `;
@@ -63,11 +63,11 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "gcr.io/k8s-skaffold/skaffold:v0.11.0",
     "currentValue": "v0.11.0",
+    "datasource": "docker",
     "depName": "gcr.io/k8s-skaffold/skaffold",
     "fromPrefix": "COPY --from=",
     "fromSuffix": "/usr/bin/skaffold /usr/bin/skaffold",
     "lineNumber": 1,
-    "purl": "pkg:docker/gcr.io/k8s-skaffold/skaffold",
   },
 ]
 `;
@@ -79,11 +79,11 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "registry.allmine.info:5005/node:8.7.0",
     "currentValue": "5005/node",
+    "datasource": "docker",
     "depName": "registry.allmine.info",
     "fromPrefix": "FROM",
     "fromSuffix": "",
     "lineNumber": 0,
-    "purl": "pkg:docker/registry.allmine.info",
   },
 ]
 `;
@@ -95,11 +95,11 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "calico/node",
     "currentValue": undefined,
+    "datasource": "docker",
     "depName": "calico/node",
     "fromPrefix": "FROM",
     "fromSuffix": "",
     "lineNumber": 0,
-    "purl": "pkg:docker/calico/node",
   },
 ]
 `;
@@ -112,11 +112,11 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "node",
     "currentValue": undefined,
+    "datasource": "docker",
     "depName": "node",
     "fromPrefix": "FROM",
     "fromSuffix": "",
     "lineNumber": 3,
-    "purl": "pkg:docker/node",
   },
 ]
 `;
@@ -129,11 +129,11 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "registry2.something.info/node:8",
     "currentValue": "8",
+    "datasource": "docker",
     "depName": "registry2.something.info/node",
     "fromPrefix": "FROM",
     "fromSuffix": "",
     "lineNumber": 0,
-    "purl": "pkg:docker/registry2.something.info/node",
   },
 ]
 `;
@@ -146,11 +146,11 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "registry2.something.info/node:8-alpine",
     "currentValue": "8-alpine",
+    "datasource": "docker",
     "depName": "registry2.something.info/node",
     "fromPrefix": "FROM",
     "fromSuffix": "",
     "lineNumber": 0,
-    "purl": "pkg:docker/registry2.something.info/node",
   },
 ]
 `;
@@ -163,11 +163,11 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "registry2.something.info/someaccount/node:8",
     "currentValue": "8",
+    "datasource": "docker",
     "depName": "registry2.something.info/someaccount/node",
     "fromPrefix": "FROM",
     "fromSuffix": "",
     "lineNumber": 0,
-    "purl": "pkg:docker/registry2.something.info/someaccount/node",
   },
 ]
 `;
@@ -179,11 +179,11 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "registry2.something.info:5005/node:8",
     "currentValue": "5005/node",
+    "datasource": "docker",
     "depName": "registry2.something.info",
     "fromPrefix": "FROM",
     "fromSuffix": "",
     "lineNumber": 0,
-    "purl": "pkg:docker/registry2.something.info",
   },
 ]
 `;
@@ -196,11 +196,11 @@ Array [
     "currentDigest": "sha256:eb85fc5b1198f5e1ec025ea07586bdbbf397e7d82df66c90d7511f533517e063",
     "currentFrom": "node@sha256:eb85fc5b1198f5e1ec025ea07586bdbbf397e7d82df66c90d7511f533517e063",
     "currentValue": undefined,
+    "datasource": "docker",
     "depName": "node",
     "fromPrefix": "FROM",
     "fromSuffix": "",
     "lineNumber": 0,
-    "purl": "pkg:docker/node",
   },
 ]
 `;
@@ -213,11 +213,11 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "node:8.9.0-alpine",
     "currentValue": "8.9.0-alpine",
+    "datasource": "docker",
     "depName": "node",
     "fromPrefix": "FROM",
     "fromSuffix": "as base",
     "lineNumber": 0,
-    "purl": "pkg:docker/node",
   },
 ]
 `;
@@ -230,11 +230,11 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "node",
     "currentValue": undefined,
+    "datasource": "docker",
     "depName": "node",
     "fromPrefix": "FROM",
     "fromSuffix": "",
     "lineNumber": 0,
-    "purl": "pkg:docker/node",
   },
 ]
 `;
@@ -247,11 +247,11 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "mynamespace/node:8",
     "currentValue": "8",
+    "datasource": "docker",
     "depName": "mynamespace/node",
     "fromPrefix": "FROM",
     "fromSuffix": "",
     "lineNumber": 0,
-    "purl": "pkg:docker/mynamespace/node",
   },
 ]
 `;
@@ -264,11 +264,11 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "node:8.9.0-alpine",
     "currentValue": "8.9.0-alpine",
+    "datasource": "docker",
     "depName": "node",
     "fromPrefix": "FROM",
     "fromSuffix": "",
     "lineNumber": 0,
-    "purl": "pkg:docker/node",
   },
 ]
 `;
@@ -281,11 +281,11 @@ Array [
     "currentDigest": "sha256:eb85fc5b1198f5e1ec025ea07586bdbbf397e7d82df66c90d7511f533517e063",
     "currentFrom": "node:8.9.0@sha256:eb85fc5b1198f5e1ec025ea07586bdbbf397e7d82df66c90d7511f533517e063",
     "currentValue": "8.9.0",
+    "datasource": "docker",
     "depName": "node",
     "fromPrefix": "FROM",
     "fromSuffix": "",
     "lineNumber": 0,
-    "purl": "pkg:docker/node",
   },
 ]
 `;
@@ -298,11 +298,11 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "node",
     "currentValue": undefined,
+    "datasource": "docker",
     "depName": "node",
     "fromPrefix": "From",
     "fromSuffix": "",
     "lineNumber": 0,
-    "purl": "pkg:docker/node",
   },
 ]
 `;
@@ -315,11 +315,11 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "node:6.12.3",
     "currentValue": "6.12.3",
+    "datasource": "docker",
     "depName": "node",
     "fromPrefix": "FROM",
     "fromSuffix": "as frontend",
     "lineNumber": 0,
-    "purl": "pkg:docker/node",
   },
 ]
 `;
@@ -332,11 +332,11 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "node:6.12.3",
     "currentValue": "6.12.3",
+    "datasource": "docker",
     "depName": "node",
     "fromPrefix": "FROM",
     "fromSuffix": "as frontend",
     "lineNumber": 0,
-    "purl": "pkg:docker/node",
   },
 ]
 `;
@@ -349,11 +349,11 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "node:6.12.3",
     "currentValue": "6.12.3",
+    "datasource": "docker",
     "depName": "node",
     "fromPrefix": "FROM",
     "fromSuffix": "as frontend",
     "lineNumber": 0,
-    "purl": "pkg:docker/node",
   },
 ]
 `;
diff --git a/test/manager/gitlabci/__snapshots__/extract.spec.js.snap b/test/manager/gitlabci/__snapshots__/extract.spec.js.snap
index 84f9219e47cbe0f3515a963f8108e3a87c8da1e7..a8613daa98156b3542a160e457cba7fa1627f78e 100644
--- a/test/manager/gitlabci/__snapshots__/extract.spec.js.snap
+++ b/test/manager/gitlabci/__snapshots__/extract.spec.js.snap
@@ -7,50 +7,50 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "hadolint/hadolint:latest",
     "currentValue": "latest",
+    "datasource": "docker",
     "depName": "hadolint/hadolint",
     "depType": "image",
     "lineNumber": 36,
-    "purl": "pkg:docker/hadolint/hadolint",
   },
   Object {
     "currentDepTag": "docker:latest",
     "currentDigest": undefined,
     "currentFrom": "docker:latest",
     "currentValue": "latest",
+    "datasource": "docker",
     "depName": "docker",
     "depType": "image",
     "lineNumber": 53,
-    "purl": "pkg:docker/docker",
   },
   Object {
     "currentDepTag": "docker:dind",
     "currentDigest": undefined,
     "currentFrom": "docker:dind",
     "currentValue": "dind",
+    "datasource": "docker",
     "depName": "docker",
     "depType": "service-image",
     "lineNumber": 55,
-    "purl": "pkg:docker/docker",
   },
   Object {
     "currentDepTag": "docker:latest",
     "currentDigest": undefined,
     "currentFrom": "docker:latest",
     "currentValue": "latest",
+    "datasource": "docker",
     "depName": "docker",
     "depType": "image",
     "lineNumber": 75,
-    "purl": "pkg:docker/docker",
   },
   Object {
     "currentDepTag": "docker:dind",
     "currentDigest": undefined,
     "currentFrom": "docker:dind",
     "currentValue": "dind",
+    "datasource": "docker",
     "depName": "docker",
     "depType": "service-image",
     "lineNumber": 77,
-    "purl": "pkg:docker/docker",
   },
 ]
 `;
diff --git a/test/manager/gomod/__snapshots__/extract.spec.js.snap b/test/manager/gomod/__snapshots__/extract.spec.js.snap
index bd6be3abd7747150f151197a4b46943aca5db4fb..72503ec35f12e8dc731087c6dcbe17bdf62e373b 100644
--- a/test/manager/gomod/__snapshots__/extract.spec.js.snap
+++ b/test/manager/gomod/__snapshots__/extract.spec.js.snap
@@ -4,577 +4,577 @@ exports[`lib/manager/gomod/extract extractPackageFile() extracts multi-line requ
 Array [
   Object {
     "currentValue": "v1.15.21",
+    "datasource": "go",
     "depName": "github.com/aws/aws-sdk-go",
     "depNameShort": "aws/aws-sdk-go",
     "depType": "require",
     "lineNumber": 3,
     "multiLine": true,
-    "purl": "pkg:go/github.com/aws/aws-sdk-go",
   },
   Object {
     "currentDigest": "9fd32a8b3d3d",
     "currentValue": "v0.0.0-20140422174119-9fd32a8b3d3d",
+    "datasource": "go",
     "depName": "github.com/bgentry/go-netrc",
     "depNameShort": "bgentry/go-netrc",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 4,
     "multiLine": true,
-    "purl": "pkg:go/github.com/bgentry/go-netrc",
   },
   Object {
     "currentDigest": "bcc4c8345a21",
     "currentValue": "v0.0.0-20151120183258-bcc4c8345a21",
+    "datasource": "go",
     "depName": "github.com/cloudfoundry/jibber_jabber",
     "depNameShort": "cloudfoundry/jibber_jabber",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 5,
     "multiLine": true,
-    "purl": "pkg:go/github.com/cloudfoundry/jibber_jabber",
   },
   Object {
     "currentValue": "v1.1.0",
+    "datasource": "go",
     "depName": "github.com/davecgh/go-spew",
     "depNameShort": "davecgh/go-spew",
     "depType": "require",
     "lineNumber": 6,
     "multiLine": true,
-    "purl": "pkg:go/github.com/davecgh/go-spew",
   },
   Object {
     "currentValue": "v1.9.0",
+    "datasource": "go",
     "depName": "github.com/emirpasic/gods",
     "depNameShort": "emirpasic/gods",
     "depType": "require",
     "lineNumber": 7,
     "multiLine": true,
-    "purl": "pkg:go/github.com/emirpasic/gods",
   },
   Object {
     "currentValue": "v1.7.0",
+    "datasource": "go",
     "depName": "github.com/fatih/color",
     "depNameShort": "fatih/color",
     "depType": "require",
     "lineNumber": 8,
     "multiLine": true,
-    "purl": "pkg:go/github.com/fatih/color",
   },
   Object {
     "currentValue": "v1.4.7",
+    "datasource": "go",
     "depName": "github.com/fsnotify/fsnotify",
     "depNameShort": "fsnotify/fsnotify",
     "depType": "require",
     "lineNumber": 9,
     "multiLine": true,
-    "purl": "pkg:go/github.com/fsnotify/fsnotify",
   },
   Object {
     "currentValue": "v1.38.2",
+    "datasource": "go",
     "depName": "github.com/go-ini/ini",
     "depNameShort": "go-ini/ini",
     "depType": "require",
     "lineNumber": 10,
     "multiLine": true,
-    "purl": "pkg:go/github.com/go-ini/ini",
   },
   Object {
     "currentDigest": "604e922904d3",
     "currentValue": "v0.0.0-20130729185459-604e922904d3",
+    "datasource": "go",
     "depName": "github.com/golang-collections/collections",
     "depNameShort": "golang-collections/collections",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 11,
     "multiLine": true,
-    "purl": "pkg:go/github.com/golang-collections/collections",
   },
   Object {
     "currentDigest": "d5fe4b57a186",
     "currentValue": "v0.0.0-20171218145408-d5fe4b57a186",
+    "datasource": "go",
     "depName": "github.com/hashicorp/go-cleanhttp",
     "depNameShort": "hashicorp/go-cleanhttp",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 12,
     "multiLine": true,
-    "purl": "pkg:go/github.com/hashicorp/go-cleanhttp",
   },
   Object {
     "currentDigest": "4bda8fa99001",
     "currentValue": "v0.0.0-20180809191950-4bda8fa99001",
+    "datasource": "go",
     "depName": "github.com/hashicorp/go-getter",
     "depNameShort": "hashicorp/go-getter",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 13,
     "multiLine": true,
-    "purl": "pkg:go/github.com/hashicorp/go-getter",
   },
   Object {
     "currentDigest": "b1a1dbde6fdc",
     "currentValue": "v0.0.0-20180326211150-b1a1dbde6fdc",
+    "datasource": "go",
     "depName": "github.com/hashicorp/go-safetemp",
     "depNameShort": "hashicorp/go-safetemp",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 14,
     "multiLine": true,
-    "purl": "pkg:go/github.com/hashicorp/go-safetemp",
   },
   Object {
     "currentValue": "v1.0.0",
+    "datasource": "go",
     "depName": "github.com/hashicorp/go-version",
     "depNameShort": "hashicorp/go-version",
     "depType": "require",
     "lineNumber": 15,
     "multiLine": true,
-    "purl": "pkg:go/github.com/hashicorp/go-version",
   },
   Object {
     "currentDigest": "ef8a98b0bbce",
     "currentValue": "v0.0.0-20180404174102-ef8a98b0bbce",
+    "datasource": "go",
     "depName": "github.com/hashicorp/hcl",
     "depNameShort": "hashicorp/hcl",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 16,
     "multiLine": true,
-    "purl": "pkg:go/github.com/hashicorp/hcl",
   },
   Object {
     "currentDigest": "fc0cef2ff331",
     "currentValue": "v0.0.0-20180515183152-fc0cef2ff331",
+    "datasource": "go",
     "depName": "github.com/heroku/rollrus",
     "depNameShort": "heroku/rollrus",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 17,
     "multiLine": true,
-    "purl": "pkg:go/github.com/heroku/rollrus",
   },
   Object {
     "currentDigest": "d14ea06fba99",
     "currentValue": "v0.0.0-20150711004518-d14ea06fba99",
+    "datasource": "go",
     "depName": "github.com/jbenet/go-context",
     "depNameShort": "jbenet/go-context",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 18,
     "multiLine": true,
-    "purl": "pkg:go/github.com/jbenet/go-context",
   },
   Object {
     "currentDigest": "906e15686e63",
     "currentValue": "v0.0.0-20180822080847-906e15686e63",
+    "datasource": "go",
     "depName": "github.com/jesseduffield/go-getter",
     "depNameShort": "jesseduffield/go-getter",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 19,
     "multiLine": true,
-    "purl": "pkg:go/github.com/jesseduffield/go-getter",
   },
   Object {
     "currentDigest": "03e26ff3f1de",
     "currentValue": "v0.0.0-20180921065632-03e26ff3f1de",
+    "datasource": "go",
     "depName": "github.com/jesseduffield/gocui",
     "depNameShort": "jesseduffield/gocui",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 20,
     "multiLine": true,
-    "purl": "pkg:go/github.com/jesseduffield/gocui",
   },
   Object {
     "currentDigest": "1e272ff78dcb",
     "currentValue": "v0.0.0-20180919093808-1e272ff78dcb",
+    "datasource": "go",
     "depName": "github.com/jesseduffield/termbox-go",
     "depNameShort": "jesseduffield/termbox-go",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 21,
     "multiLine": true,
-    "purl": "pkg:go/github.com/jesseduffield/termbox-go",
   },
   Object {
     "currentDigest": "0b12d6b521d8",
     "currentValue": "v0.0.0-20160202185014-0b12d6b521d8",
+    "datasource": "go",
     "depName": "github.com/jmespath/go-jmespath",
     "depNameShort": "jmespath/go-jmespath",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 22,
     "multiLine": true,
-    "purl": "pkg:go/github.com/jmespath/go-jmespath",
   },
   Object {
     "currentDigest": "ae77be60afb1",
     "currentValue": "v0.0.0-20170510131534-ae77be60afb1",
+    "datasource": "go",
     "depName": "github.com/kardianos/osext",
     "depNameShort": "kardianos/osext",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 23,
     "multiLine": true,
-    "purl": "pkg:go/github.com/kardianos/osext",
   },
   Object {
     "currentDigest": "9fc7bb800b55",
     "currentValue": "v0.0.0-20180317175531-9fc7bb800b55",
+    "datasource": "go",
     "depName": "github.com/kevinburke/ssh_config",
     "depNameShort": "kevinburke/ssh_config",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 24,
     "multiLine": true,
-    "purl": "pkg:go/github.com/kevinburke/ssh_config",
   },
   Object {
     "currentValue": "v1.8.0",
+    "datasource": "go",
     "depName": "github.com/magiconair/properties",
     "depNameShort": "magiconair/properties",
     "depType": "require",
     "lineNumber": 25,
     "multiLine": true,
-    "purl": "pkg:go/github.com/magiconair/properties",
   },
   Object {
     "currentValue": "v0.0.9",
+    "datasource": "go",
     "depName": "github.com/mattn/go-colorable",
     "depNameShort": "mattn/go-colorable",
     "depType": "require",
     "lineNumber": 26,
     "multiLine": true,
-    "purl": "pkg:go/github.com/mattn/go-colorable",
   },
   Object {
     "currentValue": "v0.0.3",
+    "datasource": "go",
     "depName": "github.com/mattn/go-isatty",
     "depNameShort": "mattn/go-isatty",
     "depType": "require",
     "lineNumber": 27,
     "multiLine": true,
-    "purl": "pkg:go/github.com/mattn/go-isatty",
   },
   Object {
     "currentValue": "v0.0.2",
+    "datasource": "go",
     "depName": "github.com/mattn/go-runewidth",
     "depNameShort": "mattn/go-runewidth",
     "depType": "require",
     "lineNumber": 28,
     "multiLine": true,
-    "purl": "pkg:go/github.com/mattn/go-runewidth",
   },
   Object {
     "currentValue": "v1.2.0",
+    "datasource": "go",
     "depName": "github.com/mgutz/str",
     "depNameShort": "mgutz/str",
     "depType": "require",
     "lineNumber": 29,
     "multiLine": true,
-    "purl": "pkg:go/github.com/mgutz/str",
   },
   Object {
     "currentDigest": "58046073cbff",
     "currentValue": "v0.0.0-20180801233206-58046073cbff",
+    "datasource": "go",
     "depName": "github.com/mitchellh/go-homedir",
     "depNameShort": "mitchellh/go-homedir",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 30,
     "multiLine": true,
-    "purl": "pkg:go/github.com/mitchellh/go-homedir",
   },
   Object {
     "currentDigest": "a61a99592b77",
     "currentValue": "v0.0.0-20171004221916-a61a99592b77",
+    "datasource": "go",
     "depName": "github.com/mitchellh/go-testing-interface",
     "depNameShort": "mitchellh/go-testing-interface",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 31,
     "multiLine": true,
-    "purl": "pkg:go/github.com/mitchellh/go-testing-interface",
   },
   Object {
     "currentDigest": "f15292f7a699",
     "currentValue": "v0.0.0-20180715050151-f15292f7a699",
+    "datasource": "go",
     "depName": "github.com/mitchellh/mapstructure",
     "depNameShort": "mitchellh/mapstructure",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 32,
     "multiLine": true,
-    "purl": "pkg:go/github.com/mitchellh/mapstructure",
   },
   Object {
     "currentDigest": "a16b91a3ba80",
     "currentValue": "v0.0.0-20180803040939-a16b91a3ba80",
+    "datasource": "go",
     "depName": "github.com/nicksnyder/go-i18n",
     "depNameShort": "nicksnyder/go-i18n",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 33,
     "multiLine": true,
-    "purl": "pkg:go/github.com/nicksnyder/go-i18n",
   },
   Object {
     "currentValue": "v0.2.0",
+    "datasource": "go",
     "depName": "github.com/pelletier/go-buffruneio",
     "depNameShort": "pelletier/go-buffruneio",
     "depType": "require",
     "lineNumber": 34,
     "multiLine": true,
-    "purl": "pkg:go/github.com/pelletier/go-buffruneio",
   },
   Object {
     "currentValue": "v1.2.0",
+    "datasource": "go",
     "depName": "github.com/pelletier/go-toml",
     "depNameShort": "pelletier/go-toml",
     "depType": "require",
     "lineNumber": 35,
     "multiLine": true,
-    "purl": "pkg:go/github.com/pelletier/go-toml",
   },
   Object {
     "currentValue": "v0.8.0",
+    "datasource": "go",
     "depName": "github.com/pkg/errors",
     "depNameShort": "pkg/errors",
     "depType": "require",
     "lineNumber": 36,
     "multiLine": true,
-    "purl": "pkg:go/github.com/pkg/errors",
   },
   Object {
     "currentValue": "v1.0.0",
+    "datasource": "go",
     "depName": "github.com/pmezard/go-difflib",
     "depNameShort": "pmezard/go-difflib",
     "depType": "require",
     "lineNumber": 37,
     "multiLine": true,
-    "purl": "pkg:go/github.com/pmezard/go-difflib",
   },
   Object {
     "currentValue": "v1.0.0",
+    "datasource": "go",
     "depName": "github.com/sergi/go-diff",
     "depNameShort": "sergi/go-diff",
     "depType": "require",
     "lineNumber": 38,
     "multiLine": true,
-    "purl": "pkg:go/github.com/sergi/go-diff",
   },
   Object {
     "currentDigest": "e180dbdc8da0",
     "currentValue": "v0.0.0-20170330084843-e180dbdc8da0",
+    "datasource": "go",
     "depName": "github.com/shibukawa/configdir",
     "depNameShort": "shibukawa/configdir",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 39,
     "multiLine": true,
-    "purl": "pkg:go/github.com/shibukawa/configdir",
   },
   Object {
     "currentValue": "v1.0.6",
+    "datasource": "go",
     "depName": "github.com/sirupsen/logrus",
     "depNameShort": "sirupsen/logrus",
     "depType": "require",
     "lineNumber": 40,
     "multiLine": true,
-    "purl": "pkg:go/github.com/sirupsen/logrus",
   },
   Object {
     "currentValue": "v1.1.1",
+    "datasource": "go",
     "depName": "github.com/spf13/afero",
     "depNameShort": "spf13/afero",
     "depType": "require",
     "lineNumber": 41,
     "multiLine": true,
-    "purl": "pkg:go/github.com/spf13/afero",
   },
   Object {
     "currentValue": "v1.2.0",
+    "datasource": "go",
     "depName": "github.com/spf13/cast",
     "depNameShort": "spf13/cast",
     "depType": "require",
     "lineNumber": 42,
     "multiLine": true,
-    "purl": "pkg:go/github.com/spf13/cast",
   },
   Object {
     "currentDigest": "14d3d4c51834",
     "currentValue": "v0.0.0-20180814060501-14d3d4c51834",
+    "datasource": "go",
     "depName": "github.com/spf13/jwalterweatherman",
     "depNameShort": "spf13/jwalterweatherman",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 43,
     "multiLine": true,
-    "purl": "pkg:go/github.com/spf13/jwalterweatherman",
   },
   Object {
     "currentValue": "v1.0.2",
+    "datasource": "go",
     "depName": "github.com/spf13/pflag",
     "depNameShort": "spf13/pflag",
     "depType": "require",
     "lineNumber": 44,
     "multiLine": true,
-    "purl": "pkg:go/github.com/spf13/pflag",
   },
   Object {
     "currentValue": "v1.1.0",
+    "datasource": "go",
     "depName": "github.com/spf13/viper",
     "depNameShort": "spf13/viper",
     "depType": "require",
     "lineNumber": 45,
     "multiLine": true,
-    "purl": "pkg:go/github.com/spf13/viper",
   },
   Object {
     "currentDigest": "59b7046e48ad",
     "currentValue": "v0.0.0-20160624110644-59b7046e48ad",
+    "datasource": "go",
     "depName": "github.com/spkg/bom",
     "depNameShort": "spkg/bom",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 46,
     "multiLine": true,
-    "purl": "pkg:go/github.com/spkg/bom",
   },
   Object {
     "currentValue": "v2.3.0",
+    "datasource": "go",
     "depName": "github.com/src-d/gcfg/v2",
     "depNameShort": "src-d/gcfg/v2",
     "depType": "require",
     "lineNumber": 47,
     "multiLine": true,
-    "purl": "pkg:go/github.com/src-d/gcfg/v2",
   },
   Object {
     "currentValue": "v1.2.2",
+    "datasource": "go",
     "depName": "github.com/stretchr/testify",
     "depNameShort": "stretchr/testify",
     "depType": "require",
     "lineNumber": 48,
     "multiLine": true,
-    "purl": "pkg:go/github.com/stretchr/testify",
   },
   Object {
     "currentDigest": "3627a5cbeaea",
     "currentValue": "v0.0.0-20170522205222-3627a5cbeaea",
+    "datasource": "go",
     "depName": "github.com/stvp/roll",
     "depNameShort": "stvp/roll",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 49,
     "multiLine": true,
-    "purl": "pkg:go/github.com/stvp/roll",
   },
   Object {
     "currentValue": "v0.1.2",
+    "datasource": "go",
     "depName": "github.com/tcnksm/go-gitconfig",
     "depNameShort": "tcnksm/go-gitconfig",
     "depType": "require",
     "lineNumber": 50,
     "multiLine": true,
-    "purl": "pkg:go/github.com/tcnksm/go-gitconfig",
   },
   Object {
     "currentValue": "v0.5.4",
+    "datasource": "go",
     "depName": "github.com/ulikunitz/xz",
     "depNameShort": "ulikunitz/xz",
     "depType": "require",
     "lineNumber": 51,
     "multiLine": true,
-    "purl": "pkg:go/github.com/ulikunitz/xz",
   },
   Object {
     "currentValue": "v0.2.0",
+    "datasource": "go",
     "depName": "github.com/xanzy/ssh-agent",
     "depNameShort": "xanzy/ssh-agent",
     "depType": "require",
     "lineNumber": 52,
     "multiLine": true,
-    "purl": "pkg:go/github.com/xanzy/ssh-agent",
   },
   Object {
     "currentDigest": "de0752318171",
     "currentValue": "v0.0.0-20180808211826-de0752318171",
+    "datasource": "go",
     "depName": "golang.org/x/crypto",
     "depNameShort": "golang.org/x/crypto",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 53,
     "multiLine": true,
-    "purl": "pkg:go/golang.org/x/crypto",
   },
   Object {
     "currentDigest": "c39426892332",
     "currentValue": "v0.0.0-20180811021610-c39426892332",
+    "datasource": "go",
     "depName": "golang.org/x/net",
     "depNameShort": "golang.org/x/net",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 54,
     "multiLine": true,
-    "purl": "pkg:go/golang.org/x/net",
   },
   Object {
     "currentDigest": "98c5dad5d1a0",
     "currentValue": "v0.0.0-20180810173357-98c5dad5d1a0",
+    "datasource": "go",
     "depName": "golang.org/x/sys",
     "depNameShort": "golang.org/x/sys",
     "depType": "require",
     "digestOneAndOnly": true,
     "lineNumber": 55,
     "multiLine": true,
-    "purl": "pkg:go/golang.org/x/sys",
   },
   Object {
     "currentValue": "v0.3.0",
+    "datasource": "go",
     "depName": "golang.org/x/text",
     "depNameShort": "golang.org/x/text",
     "depType": "require",
     "lineNumber": 56,
     "multiLine": true,
-    "purl": "pkg:go/golang.org/x/text",
   },
   Object {
     "currentValue": "v4.2.0",
+    "datasource": "go",
     "depName": "gopkg.in/src-d/go-billy.v4",
     "depNameShort": "src-d/go-billy",
     "depType": "require",
     "lineNumber": 57,
     "multiLine": true,
-    "purl": "pkg:go/gopkg.in/src-d/go-billy.v4",
   },
   Object {
     "currentValue": "v4.0.0-20180807092216-43d17e14b714",
+    "datasource": "go",
     "depName": "gopkg.in/src-d/go-git.v4",
     "depNameShort": "src-d/go-git",
     "depType": "require",
     "lineNumber": 58,
     "multiLine": true,
-    "purl": "pkg:go/gopkg.in/src-d/go-git.v4",
   },
   Object {
     "currentValue": "v0.1.2",
+    "datasource": "go",
     "depName": "gopkg.in/warnings.v0",
     "depNameShort": "warnings",
     "depType": "require",
     "lineNumber": 59,
     "multiLine": true,
-    "purl": "pkg:go/gopkg.in/warnings.v0",
   },
   Object {
     "currentValue": "v2.2.1",
+    "datasource": "go",
     "depName": "gopkg.in/yaml.v2",
     "depNameShort": "yaml",
     "depType": "require",
     "lineNumber": 60,
     "multiLine": true,
-    "purl": "pkg:go/gopkg.in/yaml.v2",
   },
 ]
 `;
@@ -583,35 +583,35 @@ exports[`lib/manager/gomod/extract extractPackageFile() extracts single-line req
 Array [
   Object {
     "currentValue": "v0.7.0",
+    "datasource": "go",
     "depName": "github.com/pkg/errors",
     "depNameShort": "pkg/errors",
     "depType": "require",
     "lineNumber": 2,
-    "purl": "pkg:go/github.com/pkg/errors",
   },
   Object {
     "currentValue": "v1.15.21",
+    "datasource": "go",
     "depName": "github.com/aws/aws-sdk-go",
     "depNameShort": "aws/aws-sdk-go",
     "depType": "require",
     "lineNumber": 3,
-    "purl": "pkg:go/github.com/aws/aws-sdk-go",
   },
   Object {
     "currentValue": "v1.0.0",
+    "datasource": "go",
     "depName": "github.com/davecgh/go-spew",
     "depNameShort": "davecgh/go-spew",
     "depType": "require",
     "lineNumber": 4,
-    "purl": "pkg:go/github.com/davecgh/go-spew",
   },
   Object {
     "currentValue": "v1.0.0",
+    "datasource": "go",
     "depName": "golang.org/x/foo",
     "depNameShort": "golang.org/x/foo",
     "depType": "require",
     "lineNumber": 5,
-    "purl": "pkg:go/golang.org/x/foo",
   },
   Object {
     "currentValue": "abcdef1",
@@ -622,11 +622,11 @@ Array [
   },
   Object {
     "currentValue": "v1.0.0",
+    "datasource": "go",
     "depName": "gopkg.in/russross/blackfriday.v1",
     "depNameShort": "russross/blackfriday",
     "depType": "require",
     "lineNumber": 7,
-    "purl": "pkg:go/gopkg.in/russross/blackfriday.v1",
   },
 ]
 `;
diff --git a/test/manager/gradle-wrapper/__snapshots__/extract.spec.js.snap b/test/manager/gradle-wrapper/__snapshots__/extract.spec.js.snap
index 9af5d230e32f6c2324756c78f69059a61ae4a8bf..70ab9d081c99eaaebd6eeda4dc8c5d1d809f9316 100644
--- a/test/manager/gradle-wrapper/__snapshots__/extract.spec.js.snap
+++ b/test/manager/gradle-wrapper/__snapshots__/extract.spec.js.snap
@@ -5,11 +5,11 @@ Array [
   Object {
     "checksumLineNumber": 6,
     "currentValue": "4.10.3",
+    "datasource": "gradleVersion",
     "depName": "gradle",
     "depType": "gradle-wrapper",
     "gradleWrapperType": "all",
     "lineNumber": 5,
-    "purl": "pkg:gradleVersion",
     "versionScheme": "semver",
   },
 ]
@@ -19,11 +19,11 @@ exports[`lib/manager/gradle-wrapper/extract extractPackageFile() extracts bin ve
 Array [
   Object {
     "currentValue": "4.8.0",
+    "datasource": "gradleVersion",
     "depName": "gradle",
     "depType": "gradle-wrapper",
     "gradleWrapperType": "bin",
     "lineNumber": 4,
-    "purl": "pkg:gradleVersion",
     "versionScheme": "semver",
   },
 ]
diff --git a/test/manager/kubernetes/__snapshots__/extract.spec.js.snap b/test/manager/kubernetes/__snapshots__/extract.spec.js.snap
index 2812bc45c590fc1a68d004bd4e65a8962fdcf35e..3ba76e62227194b01884fb93ea200522a5c73d15 100644
--- a/test/manager/kubernetes/__snapshots__/extract.spec.js.snap
+++ b/test/manager/kubernetes/__snapshots__/extract.spec.js.snap
@@ -7,9 +7,9 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "quay.io/external_storage/local-volume-provisioner:v2.1.0",
     "currentValue": "v2.1.0",
+    "datasource": "docker",
     "depName": "quay.io/external_storage/local-volume-provisioner",
     "lineNumber": 14,
-    "purl": "pkg:docker/quay.io/external_storage/local-volume-provisioner",
   },
 ]
 `;
@@ -21,18 +21,18 @@ Array [
     "currentDigest": undefined,
     "currentFrom": "nginx:1.7.9",
     "currentValue": "1.7.9",
+    "datasource": "docker",
     "depName": "nginx",
     "lineNumber": 18,
-    "purl": "pkg:docker/nginx",
   },
   Object {
     "currentDepTag": "k8s.gcr.io/kube-proxy-amd64:v1.11.1",
     "currentDigest": undefined,
     "currentFrom": "k8s.gcr.io/kube-proxy-amd64:v1.11.1",
     "currentValue": "v1.11.1",
+    "datasource": "docker",
     "depName": "k8s.gcr.io/kube-proxy-amd64",
     "lineNumber": 46,
-    "purl": "pkg:docker/k8s.gcr.io/kube-proxy-amd64",
   },
 ]
 `;
diff --git a/test/manager/maven/__snapshots__/extract.spec.js.snap b/test/manager/maven/__snapshots__/extract.spec.js.snap
index 308875d11fbdaca357d57039d812895ed7d206da..987c3ad64c4deb5ffd6dc13d24ffd76ba0a1194a 100644
--- a/test/manager/maven/__snapshots__/extract.spec.js.snap
+++ b/test/manager/maven/__snapshots__/extract.spec.js.snap
@@ -6,27 +6,39 @@ Object {
   "deps": Array [
     Object {
       "currentValue": "42",
+      "datasource": "maven",
       "depName": "org.example/parent",
       "fileReplacePosition": 186,
-      "purl": "pkg:maven/org.example/parent?repository_url=https://repo.maven.apache.org/maven2",
+      "registryUrls": Array [
+        "https://repo.maven.apache.org/maven2",
+      ],
     },
     Object {
       "currentValue": "0.0.1",
+      "datasource": "maven",
       "depName": "org.example/foo",
       "fileReplacePosition": 757,
-      "purl": "pkg:maven/org.example/foo?repository_url=https://repo.maven.apache.org/maven2",
+      "registryUrls": Array [
+        "https://repo.maven.apache.org/maven2",
+      ],
     },
     Object {
       "currentValue": "1.0.0",
+      "datasource": "maven",
       "depName": "org.example/bar",
       "fileReplacePosition": 905,
-      "purl": "pkg:maven/org.example/bar?repository_url=https://repo.maven.apache.org/maven2",
+      "registryUrls": Array [
+        "https://repo.maven.apache.org/maven2",
+      ],
     },
     Object {
       "currentValue": "1.8.1",
+      "datasource": "maven",
       "depName": "org.apache.maven.scm/maven-scm-provider-gitexe",
       "fileReplacePosition": 1337,
-      "purl": "pkg:maven/org.apache.maven.scm/maven-scm-provider-gitexe?repository_url=https://repo.maven.apache.org/maven2",
+      "registryUrls": Array [
+        "https://repo.maven.apache.org/maven2",
+      ],
     },
     Object {
       "currentValue": "0.0.1",
@@ -45,9 +57,12 @@ Object {
     },
     Object {
       "currentValue": "1.2.3",
+      "datasource": "maven",
       "depName": "org.example/quuz",
       "fileReplacePosition": 2529,
-      "purl": "pkg:maven/org.example/quuz?repository_url=https://repo.maven.apache.org/maven2",
+      "registryUrls": Array [
+        "https://repo.maven.apache.org/maven2",
+      ],
     },
     Object {
       "currentValue": "it's not a version",
@@ -61,9 +76,12 @@ Object {
     },
     Object {
       "currentValue": "2.17",
+      "datasource": "maven",
       "depName": "org.apache.maven.plugins/maven-checkstyle-plugin",
       "fileReplacePosition": 3218,
-      "purl": "pkg:maven/org.apache.maven.plugins/maven-checkstyle-plugin?repository_url=https://repo.maven.apache.org/maven2",
+      "registryUrls": Array [
+        "https://repo.maven.apache.org/maven2",
+      ],
     },
   ],
   "homepage": "http://example.org/index.html",
diff --git a/test/manager/meteor/__snapshots__/extract.spec.js.snap b/test/manager/meteor/__snapshots__/extract.spec.js.snap
index f11219d9951282f5ebe68a0cb3c796a77ba656b6..641f5d283308c9a3db75f676a9355188effb3fca 100644
--- a/test/manager/meteor/__snapshots__/extract.spec.js.snap
+++ b/test/manager/meteor/__snapshots__/extract.spec.js.snap
@@ -5,33 +5,33 @@ Object {
   "deps": Array [
     Object {
       "currentValue": "0.2.0",
+      "datasource": "npm",
       "depName": "xml2js",
-      "purl": "pkg:npm/xml2js",
     },
     Object {
       "currentValue": "0.6.0",
+      "datasource": "npm",
       "depName": "xml-crypto",
-      "purl": "pkg:npm/xml-crypto",
     },
     Object {
       "currentValue": "0.1.19",
+      "datasource": "npm",
       "depName": "xmldom",
-      "purl": "pkg:npm/xmldom",
     },
     Object {
       "currentValue": "2.7.10",
+      "datasource": "npm",
       "depName": "connect",
-      "purl": "pkg:npm/connect",
     },
     Object {
       "currentValue": "2.6.4",
+      "datasource": "npm",
       "depName": "xmlbuilder",
-      "purl": "pkg:npm/xmlbuilder",
     },
     Object {
       "currentValue": "0.2.0",
+      "datasource": "npm",
       "depName": "querystring",
-      "purl": "pkg:npm/querystring",
     },
   ],
 }
diff --git a/test/manager/npm/extract/__snapshots__/index.spec.js.snap b/test/manager/npm/extract/__snapshots__/index.spec.js.snap
index 7ee5f627ddca1e99f3108450ff35a040f7b90093..4af3f2c25ad41cf718a689dba54548334e6e765c 100644
--- a/test/manager/npm/extract/__snapshots__/index.spec.js.snap
+++ b/test/manager/npm/extract/__snapshots__/index.spec.js.snap
@@ -31,24 +31,24 @@ Object {
   "deps": Array [
     Object {
       "currentValue": "1.6.0",
+      "datasource": "npm",
       "depName": "angular",
       "depType": "dependencies",
       "prettyDepType": "dependency",
-      "purl": "pkg:npm/angular",
     },
     Object {
       "currentValue": "1.6.0",
+      "datasource": "npm",
       "depName": "@angular/cli",
       "depType": "devDependencies",
       "prettyDepType": "devDependency",
-      "purl": "pkg:npm/%40angular/cli",
     },
     Object {
       "currentValue": "*",
+      "datasource": "npm",
       "depName": "foo",
       "depType": "devDependencies",
       "prettyDepType": "devDependency",
-      "purl": "pkg:npm/foo",
       "skipReason": "any-version",
     },
     Object {
@@ -60,10 +60,10 @@ Object {
     },
     Object {
       "currentValue": "",
+      "datasource": "npm",
       "depName": "baz",
       "depType": "devDependencies",
       "prettyDepType": "devDependency",
-      "purl": "pkg:npm/baz",
       "skipReason": "empty",
     },
     Object {
@@ -83,30 +83,31 @@ Object {
     Object {
       "commitMessageTopic": "Node.js",
       "currentValue": ">= 8.9.2",
+      "datasource": "github",
       "depName": "node",
       "depType": "engines",
+      "lookupName": "nodejs/node",
       "major": Object {
         "enabled": false,
       },
       "prettyDepType": "engine",
-      "purl": "pkg:github/nodejs/node",
       "versionScheme": "node",
     },
     Object {
       "commitMessageTopic": "npm",
       "currentValue": "^8.0.0",
+      "datasource": "npm",
       "depName": "npm",
       "depType": "engines",
       "prettyDepType": "engine",
-      "purl": "pkg:npm/npm",
     },
     Object {
       "commitMessageTopic": "Yarn",
       "currentValue": "disabled",
+      "datasource": "npm",
       "depName": "yarn",
       "depType": "engines",
       "prettyDepType": "engine",
-      "purl": "pkg:npm/yarn",
       "skipReason": "unknown-version",
     },
   ],
@@ -146,13 +147,14 @@ Object {
     Object {
       "currentRawValue": "github:owner/c#v1.1.0",
       "currentValue": "v1.1.0",
+      "datasource": "github",
       "depName": "c",
       "depType": "dependencies",
       "gitRef": true,
       "githubRepo": "owner/c",
+      "lookupName": "owner/c",
       "pinDigests": false,
       "prettyDepType": "dependency",
-      "purl": "pkg:github/owner/c",
       "sourceUrl": "https://github.com/owner/c",
     },
     Object {
@@ -166,24 +168,26 @@ Object {
       "currentDigest": "49b5aca613b33c5b626ae68c03a385f25c142f55",
       "currentRawValue": "github:owner/e#49b5aca613b33c5b626ae68c03a385f25c142f55",
       "currentValue": null,
+      "datasource": "github",
       "depName": "e",
       "depType": "dependencies",
       "gitRef": true,
       "githubRepo": "owner/e",
+      "lookupName": "owner/e",
       "prettyDepType": "dependency",
-      "purl": "pkg:github/owner/e",
       "sourceUrl": "https://github.com/owner/e",
     },
     Object {
       "currentRawValue": "owner/f#v2.0.0",
       "currentValue": "v2.0.0",
+      "datasource": "github",
       "depName": "f",
       "depType": "dependencies",
       "gitRef": true,
       "githubRepo": "owner/f",
+      "lookupName": "owner/f",
       "pinDigests": false,
       "prettyDepType": "dependency",
-      "purl": "pkg:github/owner/f",
       "sourceUrl": "https://github.com/owner/f",
     },
     Object {
@@ -218,48 +222,52 @@ Object {
       "currentDigest": "49b5aca",
       "currentRawValue": "github:owner/k#49b5aca",
       "currentValue": null,
+      "datasource": "github",
       "depName": "k",
       "depType": "dependencies",
       "gitRef": true,
       "githubRepo": "owner/k",
+      "lookupName": "owner/k",
       "prettyDepType": "dependency",
-      "purl": "pkg:github/owner/k",
       "sourceUrl": "https://github.com/owner/k",
     },
     Object {
       "currentDigest": "abcdef0",
       "currentRawValue": "github:owner/l.git#abcdef0",
       "currentValue": null,
+      "datasource": "github",
       "depName": "l",
       "depType": "dependencies",
       "gitRef": true,
       "githubRepo": "owner/l",
+      "lookupName": "owner/l",
       "prettyDepType": "dependency",
-      "purl": "pkg:github/owner/l",
       "sourceUrl": "https://github.com/owner/l",
     },
     Object {
       "currentRawValue": "https://github.com/owner/m.git#v1.0.0",
       "currentValue": "v1.0.0",
+      "datasource": "github",
       "depName": "m",
       "depType": "dependencies",
       "gitRef": true,
       "githubRepo": "owner/m",
+      "lookupName": "owner/m",
       "pinDigests": false,
       "prettyDepType": "dependency",
-      "purl": "pkg:github/owner/m",
       "sourceUrl": "https://github.com/owner/m",
     },
     Object {
       "currentRawValue": "git+https://github.com/owner/n#v2.0.0",
       "currentValue": "v2.0.0",
+      "datasource": "github",
       "depName": "n",
       "depType": "dependencies",
       "gitRef": true,
       "githubRepo": "owner/n",
+      "lookupName": "owner/n",
       "pinDigests": false,
       "prettyDepType": "dependency",
-      "purl": "pkg:github/owner/n",
       "sourceUrl": "https://github.com/owner/n",
     },
   ],
@@ -284,45 +292,45 @@ Object {
   "deps": Array [
     Object {
       "currentValue": "6.5.0",
+      "datasource": "npm",
       "depName": "autoprefixer",
       "depType": "dependencies",
       "prettyDepType": "dependency",
-      "purl": "pkg:npm/autoprefixer",
     },
     Object {
       "currentValue": "~1.6.0",
+      "datasource": "npm",
       "depName": "bower",
       "depType": "dependencies",
       "prettyDepType": "dependency",
-      "purl": "pkg:npm/bower",
     },
     Object {
       "currentValue": "13.1.0",
+      "datasource": "npm",
       "depName": "browserify",
       "depType": "dependencies",
       "prettyDepType": "dependency",
-      "purl": "pkg:npm/browserify",
     },
     Object {
       "currentValue": "0.9.2",
+      "datasource": "npm",
       "depName": "browserify-css",
       "depType": "dependencies",
       "prettyDepType": "dependency",
-      "purl": "pkg:npm/browserify-css",
     },
     Object {
       "currentValue": "=0.22.0",
+      "datasource": "npm",
       "depName": "cheerio",
       "depType": "dependencies",
       "prettyDepType": "dependency",
-      "purl": "pkg:npm/cheerio",
     },
     Object {
       "currentValue": "1.21.0",
+      "datasource": "npm",
       "depName": "config",
       "depType": "dependencies",
       "prettyDepType": "dependency",
-      "purl": "pkg:npm/config",
     },
     Object {
       "depName": "enabled",
@@ -332,31 +340,31 @@ Object {
     },
     Object {
       "currentValue": "^1.5.8",
+      "datasource": "npm",
       "depName": "angular",
       "depType": "devDependencies",
       "prettyDepType": "devDependency",
-      "purl": "pkg:npm/angular",
     },
     Object {
       "currentValue": "1.5.8",
+      "datasource": "npm",
       "depName": "angular-touch",
       "depType": "devDependencies",
       "prettyDepType": "devDependency",
-      "purl": "pkg:npm/angular-touch",
     },
     Object {
       "currentValue": "1.5.8",
+      "datasource": "npm",
       "depName": "angular-sanitize",
       "depType": "devDependencies",
       "prettyDepType": "devDependency",
-      "purl": "pkg:npm/angular-sanitize",
     },
     Object {
       "currentValue": "4.0.0-beta.1",
+      "datasource": "npm",
       "depName": "@angular/core",
       "depType": "devDependencies",
       "prettyDepType": "devDependency",
-      "purl": "pkg:npm/%40angular/core",
     },
   ],
   "lernaClient": undefined,
@@ -401,45 +409,45 @@ Object {
   "deps": Array [
     Object {
       "currentValue": "6.5.0",
+      "datasource": "npm",
       "depName": "autoprefixer",
       "depType": "dependencies",
       "prettyDepType": "dependency",
-      "purl": "pkg:npm/autoprefixer",
     },
     Object {
       "currentValue": "~1.6.0",
+      "datasource": "npm",
       "depName": "bower",
       "depType": "dependencies",
       "prettyDepType": "dependency",
-      "purl": "pkg:npm/bower",
     },
     Object {
       "currentValue": "13.1.0",
+      "datasource": "npm",
       "depName": "browserify",
       "depType": "dependencies",
       "prettyDepType": "dependency",
-      "purl": "pkg:npm/browserify",
     },
     Object {
       "currentValue": "0.9.2",
+      "datasource": "npm",
       "depName": "browserify-css",
       "depType": "dependencies",
       "prettyDepType": "dependency",
-      "purl": "pkg:npm/browserify-css",
     },
     Object {
       "currentValue": "=0.22.0",
+      "datasource": "npm",
       "depName": "cheerio",
       "depType": "dependencies",
       "prettyDepType": "dependency",
-      "purl": "pkg:npm/cheerio",
     },
     Object {
       "currentValue": "1.21.0",
+      "datasource": "npm",
       "depName": "config",
       "depType": "dependencies",
       "prettyDepType": "dependency",
-      "purl": "pkg:npm/config",
     },
     Object {
       "depName": "enabled",
@@ -449,31 +457,31 @@ Object {
     },
     Object {
       "currentValue": "^1.5.8",
+      "datasource": "npm",
       "depName": "angular",
       "depType": "devDependencies",
       "prettyDepType": "devDependency",
-      "purl": "pkg:npm/angular",
     },
     Object {
       "currentValue": "1.5.8",
+      "datasource": "npm",
       "depName": "angular-touch",
       "depType": "devDependencies",
       "prettyDepType": "devDependency",
-      "purl": "pkg:npm/angular-touch",
     },
     Object {
       "currentValue": "1.5.8",
+      "datasource": "npm",
       "depName": "angular-sanitize",
       "depType": "devDependencies",
       "prettyDepType": "devDependency",
-      "purl": "pkg:npm/angular-sanitize",
     },
     Object {
       "currentValue": "4.0.0-beta.1",
+      "datasource": "npm",
       "depName": "@angular/core",
       "depType": "devDependencies",
       "prettyDepType": "devDependency",
-      "purl": "pkg:npm/%40angular/core",
     },
   ],
   "lernaClient": "npm",
@@ -497,45 +505,45 @@ Object {
   "deps": Array [
     Object {
       "currentValue": "6.5.0",
+      "datasource": "npm",
       "depName": "autoprefixer",
       "depType": "dependencies",
       "prettyDepType": "dependency",
-      "purl": "pkg:npm/autoprefixer",
     },
     Object {
       "currentValue": "~1.6.0",
+      "datasource": "npm",
       "depName": "bower",
       "depType": "dependencies",
       "prettyDepType": "dependency",
-      "purl": "pkg:npm/bower",
     },
     Object {
       "currentValue": "13.1.0",
+      "datasource": "npm",
       "depName": "browserify",
       "depType": "dependencies",
       "prettyDepType": "dependency",
-      "purl": "pkg:npm/browserify",
     },
     Object {
       "currentValue": "0.9.2",
+      "datasource": "npm",
       "depName": "browserify-css",
       "depType": "dependencies",
       "prettyDepType": "dependency",
-      "purl": "pkg:npm/browserify-css",
     },
     Object {
       "currentValue": "=0.22.0",
+      "datasource": "npm",
       "depName": "cheerio",
       "depType": "dependencies",
       "prettyDepType": "dependency",
-      "purl": "pkg:npm/cheerio",
     },
     Object {
       "currentValue": "1.21.0",
+      "datasource": "npm",
       "depName": "config",
       "depType": "dependencies",
       "prettyDepType": "dependency",
-      "purl": "pkg:npm/config",
     },
     Object {
       "depName": "enabled",
@@ -545,31 +553,31 @@ Object {
     },
     Object {
       "currentValue": "^1.5.8",
+      "datasource": "npm",
       "depName": "angular",
       "depType": "devDependencies",
       "prettyDepType": "devDependency",
-      "purl": "pkg:npm/angular",
     },
     Object {
       "currentValue": "1.5.8",
+      "datasource": "npm",
       "depName": "angular-touch",
       "depType": "devDependencies",
       "prettyDepType": "devDependency",
-      "purl": "pkg:npm/angular-touch",
     },
     Object {
       "currentValue": "1.5.8",
+      "datasource": "npm",
       "depName": "angular-sanitize",
       "depType": "devDependencies",
       "prettyDepType": "devDependency",
-      "purl": "pkg:npm/angular-sanitize",
     },
     Object {
       "currentValue": "4.0.0-beta.1",
+      "datasource": "npm",
       "depName": "@angular/core",
       "depType": "devDependencies",
       "prettyDepType": "devDependency",
-      "purl": "pkg:npm/%40angular/core",
     },
   ],
   "lernaClient": undefined,
diff --git a/test/manager/nuget/__snapshots__/extract.spec.js.snap b/test/manager/nuget/__snapshots__/extract.spec.js.snap
index 99c6572423a31d3eb60afe16e2d93140fe1d6ed6..8928e6a1f20bd3b551eb343f93d2863313aaebac 100644
--- a/test/manager/nuget/__snapshots__/extract.spec.js.snap
+++ b/test/manager/nuget/__snapshots__/extract.spec.js.snap
@@ -4,87 +4,87 @@ exports[`lib/manager/nuget/extract extractPackageFile() extracts all dependencie
 Array [
   Object {
     "currentValue": "4.5.0",
+    "datasource": "nuget",
     "depName": "Autofac",
     "depType": "nuget",
     "lineNumber": 12,
-    "purl": "pkg:nuget/Autofac",
   },
   Object {
     "currentValue": "4.1.0",
+    "datasource": "nuget",
     "depName": "Autofac.Extensions.DependencyInjection",
     "depType": "nuget",
     "lineNumber": 13,
-    "purl": "pkg:nuget/Autofac.Extensions.DependencyInjection",
   },
   Object {
     "currentValue": "1.1.2",
+    "datasource": "nuget",
     "depName": "Microsoft.AspNetCore.Hosting",
     "depType": "nuget",
     "lineNumber": 14,
-    "purl": "pkg:nuget/Microsoft.AspNetCore.Hosting",
   },
   Object {
     "currentValue": "1.1.3",
+    "datasource": "nuget",
     "depName": "Microsoft.AspNetCore.Mvc.Core",
     "depType": "nuget",
     "lineNumber": 15,
-    "purl": "pkg:nuget/Microsoft.AspNetCore.Mvc.Core",
   },
   Object {
     "currentValue": "1.1.2",
+    "datasource": "nuget",
     "depName": "Microsoft.AspNetCore.Server.Kestrel",
     "depType": "nuget",
     "lineNumber": 16,
-    "purl": "pkg:nuget/Microsoft.AspNetCore.Server.Kestrel",
   },
   Object {
     "currentValue": "1.1.2",
+    "datasource": "nuget",
     "depName": "Microsoft.Extensions.Configuration.Json",
     "depType": "nuget",
     "lineNumber": 17,
-    "purl": "pkg:nuget/Microsoft.Extensions.Configuration.Json",
   },
   Object {
     "currentValue": "1.1.2",
+    "datasource": "nuget",
     "depName": "Microsoft.Extensions.Logging.Debug",
     "depType": "nuget",
     "lineNumber": 18,
-    "purl": "pkg:nuget/Microsoft.Extensions.Logging.Debug",
   },
   Object {
     "currentValue": "10.0.2",
+    "datasource": "nuget",
     "depName": "Newtonsoft.Json",
     "depType": "nuget",
     "lineNumber": 19,
-    "purl": "pkg:nuget/Newtonsoft.Json",
   },
   Object {
     "currentValue": "2.4.0",
+    "datasource": "nuget",
     "depName": "Serilog",
     "depType": "nuget",
     "lineNumber": 20,
-    "purl": "pkg:nuget/Serilog",
   },
   Object {
     "currentValue": "1.4.0",
+    "datasource": "nuget",
     "depName": "Serilog.Extensions.Logging",
     "depType": "nuget",
     "lineNumber": 21,
-    "purl": "pkg:nuget/Serilog.Extensions.Logging",
   },
   Object {
     "currentValue": "2.1.0",
+    "datasource": "nuget",
     "depName": "Serilog.Sinks.Literate",
     "depType": "nuget",
     "lineNumber": 22,
-    "purl": "pkg:nuget/Serilog.Sinks.Literate",
   },
   Object {
     "currentValue": "3.1.0.5",
+    "datasource": "nuget",
     "depName": "Stateless",
     "depType": "nuget",
     "lineNumber": 23,
-    "purl": "pkg:nuget/Stateless",
     "skipReason": "not-version",
   },
 ]
diff --git a/test/manager/nvm/__snapshots__/extract.spec.js.snap b/test/manager/nvm/__snapshots__/extract.spec.js.snap
index ce706901a1399a049bb59321cb9ea2bbad47d72f..02783992f7b11147b962660c092ff7f7dc075151 100644
--- a/test/manager/nvm/__snapshots__/extract.spec.js.snap
+++ b/test/manager/nvm/__snapshots__/extract.spec.js.snap
@@ -4,8 +4,9 @@ exports[`lib/manager/nvm/extract extractPackageFile() returns a result 1`] = `
 Array [
   Object {
     "currentValue": "8.4.0",
+    "datasource": "github",
     "depName": "node",
-    "purl": "pkg:github/nodejs/node",
+    "lookupName": "nodejs/node",
   },
 ]
 `;
@@ -14,8 +15,9 @@ exports[`lib/manager/nvm/extract extractPackageFile() skips non ranges 1`] = `
 Array [
   Object {
     "currentValue": "latestn",
+    "datasource": "github",
     "depName": "node",
-    "purl": "pkg:github/nodejs/node",
+    "lookupName": "nodejs/node",
     "skipReason": "unsupported-version",
   },
 ]
@@ -25,8 +27,9 @@ exports[`lib/manager/nvm/extract extractPackageFile() supports ranges 1`] = `
 Array [
   Object {
     "currentValue": "8.4",
+    "datasource": "github",
     "depName": "node",
-    "purl": "pkg:github/nodejs/node",
+    "lookupName": "nodejs/node",
   },
 ]
 `;
diff --git a/test/manager/pip_requirements/__snapshots__/extract.spec.js.snap b/test/manager/pip_requirements/__snapshots__/extract.spec.js.snap
index 1da9173d42bf9a001eb30e312f2df134e7802a99..89b2a6e05b5836d9ba479c3acd6b41838cb6aeb3 100644
--- a/test/manager/pip_requirements/__snapshots__/extract.spec.js.snap
+++ b/test/manager/pip_requirements/__snapshots__/extract.spec.js.snap
@@ -4,27 +4,27 @@ exports[`lib/manager/pip_requirements/extract extractPackageFile() extracts depe
 Array [
   Object {
     "currentValue": "==0.3.1",
+    "datasource": "pypi",
     "depName": "some-package",
     "lineNumber": 2,
-    "purl": "pkg:pypi/some-package",
     "registryUrls": Array [
       "http://example.com/private-pypi/",
     ],
   },
   Object {
     "currentValue": "==1.0.0",
+    "datasource": "pypi",
     "depName": "some-other-package",
     "lineNumber": 3,
-    "purl": "pkg:pypi/some-other-package",
     "registryUrls": Array [
       "http://example.com/private-pypi/",
     ],
   },
   Object {
     "currentValue": "==1.9",
+    "datasource": "pypi",
     "depName": "not_semver",
     "lineNumber": 4,
-    "purl": "pkg:pypi/not_semver",
     "registryUrls": Array [
       "http://example.com/private-pypi/",
     ],
@@ -36,33 +36,33 @@ exports[`lib/manager/pip_requirements/extract extractPackageFile() extracts mult
 Array [
   Object {
     "currentValue": "==1",
+    "datasource": "pypi",
     "depName": "Django",
     "lineNumber": 0,
-    "purl": "pkg:pypi/Django",
   },
   Object {
     "currentValue": "==0.6.27",
+    "datasource": "pypi",
     "depName": "distribute",
     "lineNumber": 1,
-    "purl": "pkg:pypi/distribute",
   },
   Object {
     "currentValue": "==0.2",
+    "datasource": "pypi",
     "depName": "dj-database-url",
     "lineNumber": 2,
-    "purl": "pkg:pypi/dj-database-url",
   },
   Object {
     "currentValue": "==2.4.5",
+    "datasource": "pypi",
     "depName": "psycopg2",
     "lineNumber": 3,
-    "purl": "pkg:pypi/psycopg2",
   },
   Object {
     "currentValue": "==0.1.2",
+    "datasource": "pypi",
     "depName": "wsgiref",
     "lineNumber": 4,
-    "purl": "pkg:pypi/wsgiref",
   },
 ]
 `;
@@ -71,34 +71,34 @@ exports[`lib/manager/pip_requirements/extract extractPackageFile() handles comme
 Array [
   Object {
     "currentValue": "==1.2.7",
+    "datasource": "pypi",
     "depName": "Django",
     "lineNumber": 0,
-    "purl": "pkg:pypi/Django",
   },
   Object {
     "currentValue": "==0.6.27",
+    "datasource": "pypi",
     "depName": "distribute",
     "lineNumber": 1,
-    "purl": "pkg:pypi/distribute",
     "skipReason": "ignored",
   },
   Object {
     "currentValue": "==0.2",
+    "datasource": "pypi",
     "depName": "dj-database-url",
     "lineNumber": 2,
-    "purl": "pkg:pypi/dj-database-url",
   },
   Object {
     "currentValue": "==2.4.5",
+    "datasource": "pypi",
     "depName": "psycopg2",
     "lineNumber": 3,
-    "purl": "pkg:pypi/psycopg2",
   },
   Object {
     "currentValue": "==0.1.2",
+    "datasource": "pypi",
     "depName": "wsgiref",
     "lineNumber": 4,
-    "purl": "pkg:pypi/wsgiref",
   },
 ]
 `;
@@ -107,21 +107,21 @@ exports[`lib/manager/pip_requirements/extract extractPackageFile() handles extra
 Array [
   Object {
     "currentValue": "==2.0.8",
+    "datasource": "pypi",
     "depName": "Django",
     "lineNumber": 0,
-    "purl": "pkg:pypi/Django",
   },
   Object {
     "currentValue": "==4.1.1",
+    "datasource": "pypi",
     "depName": "celery",
     "lineNumber": 1,
-    "purl": "pkg:pypi/celery",
   },
   Object {
     "currentValue": " == 3.2.1",
+    "datasource": "pypi",
     "depName": "foo",
     "lineNumber": 2,
-    "purl": "pkg:pypi/foo",
   },
 ]
 `;
diff --git a/test/manager/pip_setup/__snapshots__/extract.spec.js.snap b/test/manager/pip_setup/__snapshots__/extract.spec.js.snap
index 021bd92abdd771462013304ec2e40770b16863b0..caa0d0d179845421687ab31866cbd7e467bf9c3d 100644
--- a/test/manager/pip_setup/__snapshots__/extract.spec.js.snap
+++ b/test/manager/pip_setup/__snapshots__/extract.spec.js.snap
@@ -5,94 +5,94 @@ Object {
   "deps": Array [
     Object {
       "currentValue": ">=3.1.13.0,<5.0",
+      "datasource": "pypi",
       "depName": "celery",
       "lineNumber": 36,
-      "purl": "pkg:pypi/celery",
     },
     Object {
       "currentValue": ">=1.7",
+      "datasource": "pypi",
       "depName": "logging_tree",
       "lineNumber": 39,
-      "purl": "pkg:pypi/logging_tree",
     },
     Object {
       "currentValue": ">=2.2",
+      "datasource": "pypi",
       "depName": "pygments",
       "lineNumber": 40,
-      "purl": "pkg:pypi/pygments",
     },
     Object {
       "currentValue": ">=5.0",
+      "datasource": "pypi",
       "depName": "psutil",
       "lineNumber": 41,
-      "purl": "pkg:pypi/psutil",
     },
     Object {
       "currentValue": ">=3.0",
+      "datasource": "pypi",
       "depName": "objgraph",
       "lineNumber": 42,
-      "purl": "pkg:pypi/objgraph",
     },
     Object {
       "currentValue": ">=1.10,<2.0",
+      "datasource": "pypi",
       "depName": "django",
       "lineNumber": 45,
-      "purl": "pkg:pypi/django",
     },
     Object {
       "currentValue": ">=0.11,<2.0",
+      "datasource": "pypi",
       "depName": "flask",
       "lineNumber": 48,
-      "purl": "pkg:pypi/flask",
     },
     Object {
       "currentValue": ">=1.4,<2.0",
+      "datasource": "pypi",
       "depName": "blinker",
       "lineNumber": 49,
-      "purl": "pkg:pypi/blinker",
     },
     Object {
       "currentValue": ">=19.7.0,<20.0",
+      "datasource": "pypi",
       "depName": "gunicorn",
       "lineNumber": 61,
-      "purl": "pkg:pypi/gunicorn",
     },
     Object {
       "currentValue": ">=0.11.5,<0.15",
+      "datasource": "pypi",
       "depName": "Werkzeug",
       "lineNumber": 62,
-      "purl": "pkg:pypi/Werkzeug",
     },
     Object {
       "currentValue": ">=3.2.1,<4.0",
+      "datasource": "pypi",
       "depName": "statsd",
       "lineNumber": 63,
-      "purl": "pkg:pypi/statsd",
     },
     Object {
       "currentValue": ">=2.10.0,<3.0",
+      "datasource": "pypi",
       "depName": "requests",
       "lineNumber": 64,
-      "purl": "pkg:pypi/requests",
       "skipReason": "ignored",
     },
     Object {
       "currentValue": ">=5.27.1,<7.0",
+      "datasource": "pypi",
       "depName": "raven",
       "lineNumber": 65,
-      "purl": "pkg:pypi/raven",
     },
     Object {
       "currentValue": ">=0.15.2,<0.17",
+      "datasource": "pypi",
       "depName": "future",
       "lineNumber": 66,
-      "purl": "pkg:pypi/future",
     },
     Object {
       "currentValue": ">=1.0.16,<2.0",
+      "datasource": "pypi",
       "depName": "ipaddress",
       "lineNumber": 67,
-      "purl": "pkg:pypi/ipaddress",
     },
   ],
 }
diff --git a/test/manager/pipenv/__snapshots__/extract.spec.js.snap b/test/manager/pipenv/__snapshots__/extract.spec.js.snap
index 06cb2c899a88431b46334444c032a475b11f1e68..e19291857dc075ec3200dda60e70569a91b99026 100644
--- a/test/manager/pipenv/__snapshots__/extract.spec.js.snap
+++ b/test/manager/pipenv/__snapshots__/extract.spec.js.snap
@@ -4,10 +4,10 @@ exports[`lib/manager/pipenv/extract extractPackageFile() extracts dependencies 1
 Array [
   Object {
     "currentValue": "==0.3.1",
+    "datasource": "pypi",
     "depName": "some-package",
     "depType": "packages",
     "pipenvNestedVersion": false,
-    "purl": "pkg:pypi/some-package",
     "registryUrls": Array [
       "https://pypi.org/pypi/",
       "http://example.com/private-pypi/",
@@ -15,10 +15,10 @@ Array [
   },
   Object {
     "currentValue": "==1.0.0",
+    "datasource": "pypi",
     "depName": "some-other-package",
     "depType": "packages",
     "pipenvNestedVersion": false,
-    "purl": "pkg:pypi/some-other-package",
     "registryUrls": Array [
       "https://pypi.org/pypi/",
       "http://example.com/private-pypi/",
@@ -26,10 +26,10 @@ Array [
   },
   Object {
     "currentValue": "==1.0.0",
+    "datasource": "pypi",
     "depName": "pytest-benchmark",
     "depType": "packages",
     "pipenvNestedVersion": true,
-    "purl": "pkg:pypi/pytest-benchmark",
     "registryUrls": Array [
       "https://pypi.org/pypi/",
       "http://example.com/private-pypi/",
@@ -37,10 +37,10 @@ Array [
   },
   Object {
     "currentValue": "==0.1.0",
+    "datasource": "pypi",
     "depName": "dev-package",
     "depType": "dev-packages",
     "pipenvNestedVersion": false,
-    "purl": "pkg:pypi/dev-package",
     "registryUrls": Array [
       "https://pypi.org/pypi/",
       "http://example.com/private-pypi/",
@@ -53,50 +53,50 @@ exports[`lib/manager/pipenv/extract extractPackageFile() extracts multiple depen
 Array [
   Object {
     "currentValue": "==1",
+    "datasource": "pypi",
     "depName": "Django",
     "depType": "packages",
     "pipenvNestedVersion": false,
-    "purl": "pkg:pypi/Django",
     "registryUrls": Array [
       "https://pypi.org/pypi/",
     ],
   },
   Object {
     "currentValue": "==0.6.27",
+    "datasource": "pypi",
     "depName": "distribute",
     "depType": "packages",
     "pipenvNestedVersion": false,
-    "purl": "pkg:pypi/distribute",
     "registryUrls": Array [
       "https://pypi.org/pypi/",
     ],
   },
   Object {
     "currentValue": "==0.2",
+    "datasource": "pypi",
     "depName": "dj-database-url",
     "depType": "packages",
     "pipenvNestedVersion": false,
-    "purl": "pkg:pypi/dj-database-url",
     "registryUrls": Array [
       "https://pypi.org/pypi/",
     ],
   },
   Object {
     "currentValue": "==2.4.5",
+    "datasource": "pypi",
     "depName": "psycopg2",
     "depType": "packages",
     "pipenvNestedVersion": false,
-    "purl": "pkg:pypi/psycopg2",
     "registryUrls": Array [
       "https://pypi.org/pypi/",
     ],
   },
   Object {
     "currentValue": "==0.1.2",
+    "datasource": "pypi",
     "depName": "wsgiref",
     "depType": "packages",
     "pipenvNestedVersion": false,
-    "purl": "pkg:pypi/wsgiref",
     "registryUrls": Array [
       "https://pypi.org/pypi/",
     ],
diff --git a/test/manager/terraform/__snapshots__/extract.spec.js.snap b/test/manager/terraform/__snapshots__/extract.spec.js.snap
index fad516ed5988bd79a64743c6736cf3681c9bb6f6..70d701dd62b4587104d0ae7770190195c7057b1a 100644
--- a/test/manager/terraform/__snapshots__/extract.spec.js.snap
+++ b/test/manager/terraform/__snapshots__/extract.spec.js.snap
@@ -5,124 +5,129 @@ Object {
   "deps": Array [
     Object {
       "currentValue": "v1.0.0",
+      "datasource": "github",
       "depName": "github.com/hashicorp/example",
       "depNameShort": "hashicorp/example",
       "depType": "github",
       "lineNumber": 1,
+      "lookupName": "hashicorp/example",
       "moduleName": "foo",
-      "purl": "pkg:github/hashicorp/example",
       "source": "github.com/hashicorp/example?ref=v1.0.0",
     },
     Object {
       "currentValue": "next",
+      "datasource": "github",
       "depName": "github.com/hashicorp/example",
       "depNameShort": "hashicorp/example",
       "depType": "github",
       "lineNumber": 5,
+      "lookupName": "hashicorp/example",
       "moduleName": "bar",
-      "purl": "pkg:github/hashicorp/example",
       "skipReason": "unsupported-version",
       "source": "github.com/hashicorp/example?ref=next",
     },
     Object {
       "currentValue": "0.1.0",
+      "datasource": "terraform",
       "depName": "hashicorp/consul/aws",
       "depNameShort": "hashicorp/consul/aws",
       "depType": "terraform",
       "lineNumber": 10,
       "moduleName": "consul",
-      "purl": "pkg:terraform/hashicorp/consul/aws",
       "source": "hashicorp/consul/aws",
     },
     Object {
       "currentValue": "v0.1.0",
+      "datasource": "github",
       "depName": "github.com/tieto-cem/terraform-aws-ecs-task-definition",
       "depNameShort": "tieto-cem/terraform-aws-ecs-task-definition",
       "depType": "github",
       "lineNumber": 14,
+      "lookupName": "tieto-cem/terraform-aws-ecs-task-definition",
       "moduleName": "container_definition",
-      "purl": "pkg:github/tieto-cem/terraform-aws-ecs-task-definition",
       "source": "github.com/tieto-cem/terraform-aws-ecs-task-definition//modules/container-definition?ref=v0.1.0",
     },
     Object {
       "currentValue": "v0.1.0",
+      "datasource": "github",
       "depName": "github.com/tieto-cem/terraform-aws-ecs-task-definition",
       "depNameShort": "tieto-cem/terraform-aws-ecs-task-definition",
       "depType": "github",
       "lineNumber": 25,
+      "lookupName": "tieto-cem/terraform-aws-ecs-task-definition",
       "moduleName": "task_definition",
-      "purl": "pkg:github/tieto-cem/terraform-aws-ecs-task-definition",
       "source": "github.com/tieto-cem/terraform-aws-ecs-task-definition?ref=v0.1.0",
     },
     Object {
       "currentValue": "v2.0.0",
+      "datasource": "github",
       "depName": "github.com/hashicorp/example",
       "depNameShort": "hashicorp/example",
       "depType": "github",
       "lineNumber": 31,
+      "lookupName": "hashicorp/example",
       "moduleName": "consul",
-      "purl": "pkg:github/hashicorp/example",
       "source": "git@github.com:hashicorp/example.git?ref=v2.0.0",
     },
     Object {
+      "datasource": "terraform",
       "depName": "terraform-aws-modules/security-group/aws",
       "depNameShort": "terraform-aws-modules/security-group/aws",
       "depType": "terraform",
       "lineNumber": undefined,
       "moduleName": "web_server_sg",
-      "purl": "pkg:terraform/terraform-aws-modules/security-group/aws",
       "skipReason": "no-version",
       "source": "terraform-aws-modules/security-group/aws//modules/http-80",
     },
     Object {
       "currentValue": "<= 2.4.0",
+      "datasource": "terraform",
       "depName": "terraform-aws-modules/security-group/aws",
       "depNameShort": "terraform-aws-modules/security-group/aws",
       "depType": "terraform",
       "lineNumber": 46,
       "moduleName": "vote_service_sg",
-      "purl": "pkg:terraform/terraform-aws-modules/security-group/aws",
       "source": "terraform-aws-modules/security-group/aws",
     },
     Object {
       "currentValue": "~> 1.1.0",
+      "datasource": "terraform",
       "depName": "app.terraform.io/example-corp/k8s-cluster/azurerm",
       "depNameShort": "app.terraform.io/example-corp/k8s-cluster/azurerm",
       "depType": "terraform",
       "lineNumber": 71,
       "moduleName": "consul",
-      "purl": "pkg:terraform/app.terraform.io/example-corp/k8s-cluster/azurerm",
       "source": "app.terraform.io/example-corp/k8s-cluster/azurerm",
     },
     Object {
       "currentValue": "~> 1.1",
+      "datasource": "terraform",
       "depName": "app.terraform.io/example-corp/k8s-cluster/azurerm",
       "depNameShort": "app.terraform.io/example-corp/k8s-cluster/azurerm",
       "depType": "terraform",
       "lineNumber": 76,
       "moduleName": "consul2",
-      "purl": "pkg:terraform/app.terraform.io/example-corp/k8s-cluster/azurerm",
       "source": "app.terraform.io/example-corp/k8s-cluster/azurerm",
     },
     Object {
       "currentValue": "~~ 1.1",
+      "datasource": "terraform",
       "depName": "app.terraform.io/example-corp/k8s-cluster/azurerm",
       "depNameShort": "app.terraform.io/example-corp/k8s-cluster/azurerm",
       "depType": "terraform",
       "lineNumber": 81,
       "moduleName": "consul3",
-      "purl": "pkg:terraform/app.terraform.io/example-corp/k8s-cluster/azurerm",
       "skipReason": "unsupported-version",
       "source": "app.terraform.io/example-corp/k8s-cluster/azurerm",
     },
     Object {
       "currentValue": ">= 1.0.0, <= 2.0.0",
+      "datasource": "terraform",
       "depName": "hashicorp/consul/aws",
       "depNameShort": "hashicorp/consul/aws",
       "depType": "terraform",
       "lineNumber": 86,
       "moduleName": "consul3",
-      "purl": "pkg:terraform/hashicorp/consul/aws",
       "source": "hashicorp/consul/aws",
     },
     Object {
diff --git a/test/manager/terraform/update.spec.js b/test/manager/terraform/update.spec.js
index 7f69e7007d897a8b55dc71ab89769cf816550c75..cdb229f6e650ff6e799f9d87d7f6d09643d3cc41 100644
--- a/test/manager/terraform/update.spec.js
+++ b/test/manager/terraform/update.spec.js
@@ -48,7 +48,6 @@ describe('manager/terraform/update', () => {
         depNameShort: 'tieto-cem/terraform-aws-ecs-task-definition',
         lineNumber: 14,
         moduleName: 'container_definition',
-        purl: 'pkg:github/tieto-cem/terraform-aws-ecs-task-definition',
         source:
           'github.com/tieto-cem/terraform-aws-ecs-task-definition//modules/container-definition?ref=v0.1.0',
       };
@@ -64,7 +63,6 @@ describe('manager/terraform/update', () => {
         depType: 'terraform',
         lineNumber: 11,
         moduleName: 'consul',
-        purl: 'pkg:terraform/hashicorp/consul/aws',
         source: 'hashicorp/consul/aws',
         newValue: '0.4.0',
       };
@@ -79,7 +77,6 @@ describe('manager/terraform/update', () => {
         depType: 'terraform',
         lineNumber: 10,
         moduleName: 'consul',
-        purl: 'pkg:terraform/hashicorp/consul/aws',
         source: 'hashicorp/consul/aws',
         newValue: '0.4.0',
       };
diff --git a/test/util/__snapshots__/purl.spec.js.snap b/test/util/__snapshots__/purl.spec.js.snap
deleted file mode 100644
index 4bfeba0066209d5daf14b22d30eb51757a17febb..0000000000000000000000000000000000000000
--- a/test/util/__snapshots__/purl.spec.js.snap
+++ /dev/null
@@ -1,54 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`util/purl parse() parses github with subpath/lookupType 1`] = `
-Object {
-  "datasource": "github",
-  "lookupName": "abc/def",
-  "lookupType": "releases",
-}
-`;
-
-exports[`util/purl parse() parses namespaced npm 1`] = `
-Object {
-  "datasource": "npm",
-  "lookupName": "@foo/bar",
-}
-`;
-
-exports[`util/purl parse() parses namespaced npm with version 1`] = `
-Object {
-  "datasource": "npm",
-  "lookupName": "@foo/bar",
-}
-`;
-
-exports[`util/purl parse() parses npm with version and 1 qualifier 1`] = `
-Object {
-  "datasource": "npm",
-  "lookupName": "foo",
-}
-`;
-
-exports[`util/purl parse() parses npm with version and 2 qualifiers 1`] = `
-Object {
-  "datasource": "npm",
-  "lookupName": "foo",
-}
-`;
-
-exports[`util/purl parse() parses repository_url qualifier 1`] = `
-Object {
-  "datasource": "maven",
-  "lookupName": "org.apache.xmlgraphics/batik-anim",
-  "registryUrls": Array [
-    "repo.spring.io/release",
-  ],
-}
-`;
-
-exports[`util/purl parse() parses simple npm 1`] = `
-Object {
-  "datasource": "npm",
-  "lookupName": "foo",
-}
-`;
diff --git a/test/util/purl.spec.js b/test/util/purl.spec.js
deleted file mode 100644
index 96cf12db118585c6cc441e2c75a2157fbe2db282..0000000000000000000000000000000000000000
--- a/test/util/purl.spec.js
+++ /dev/null
@@ -1,37 +0,0 @@
-const { parse } = require('../../lib/util/purl');
-
-describe('util/purl', () => {
-  describe('parse()', () => {
-    it('returns null for null', () => {
-      expect(parse(null)).toBe(null);
-    });
-    it('returns null if not pkg', () => {
-      expect(parse('foo:bar')).toBe(null);
-    });
-    it('parses simple npm', () => {
-      expect(parse('pkg:npm/foo')).toMatchSnapshot();
-    });
-    it('parses namespaced npm', () => {
-      expect(parse('pkg:npm/%40foo/bar')).toMatchSnapshot();
-    });
-    it('parses namespaced npm with version', () => {
-      expect(parse('pkg:npm/%40foo/bar@1.0.0')).toMatchSnapshot();
-    });
-    it('parses npm with version and 1 qualifier', () => {
-      expect(parse('pkg:npm/foo@1.0.0?a=b')).toMatchSnapshot();
-    });
-    it('parses npm with version and 2 qualifiers', () => {
-      expect(parse('pkg:npm/foo@1.0.0?a=b&c=d')).toMatchSnapshot();
-    });
-    it('parses github with subpath/lookupType', () => {
-      expect(parse('pkg:github/abc/def#releases')).toMatchSnapshot();
-    });
-    it('parses repository_url qualifier', () => {
-      expect(
-        parse(
-          'pkg:maven/org.apache.xmlgraphics/batik-anim@1.9.1?repository_url=repo.spring.io/release'
-        )
-      ).toMatchSnapshot();
-    });
-  });
-});
diff --git a/test/workers/repository/process/__snapshots__/fetch.spec.js.snap b/test/workers/repository/process/__snapshots__/fetch.spec.js.snap
index 2d18b55afbc6b09317b6c3ba7002e9ab5262dd5f..7b8d17a9e56a4d071d99b4cae87541ee3e9cba29 100644
--- a/test/workers/repository/process/__snapshots__/fetch.spec.js.snap
+++ b/test/workers/repository/process/__snapshots__/fetch.spec.js.snap
@@ -6,9 +6,9 @@ Object {
     Object {
       "deps": Array [
         Object {
+          "datasource": "npm",
           "depName": "aaa",
           "depType": "devDependencies",
-          "purl": "pkg:npm/aaa",
           "updates": Array [
             "a",
             "b",
diff --git a/test/workers/repository/process/fetch.spec.js b/test/workers/repository/process/fetch.spec.js
index 90839717f334a0bb4d54366aedb85ce2d69f5fc1..f0dae4a747a45df73bda4dd87d17c12a21712b13 100644
--- a/test/workers/repository/process/fetch.spec.js
+++ b/test/workers/repository/process/fetch.spec.js
@@ -63,9 +63,9 @@ describe('workers/repository/process/fetch', () => {
             packageJsonType: 'app',
             deps: [
               {
+                datasource: 'npm',
                 depName: 'aaa',
                 depType: 'devDependencies',
-                purl: 'pkg:npm/aaa',
               },
               { depName: 'bbb', depType: 'dependencies' },
             ],
diff --git a/test/workers/repository/process/lookup/__snapshots__/index.spec.js.snap b/test/workers/repository/process/lookup/__snapshots__/index.spec.js.snap
index 4bca86f695ff647b960f92d93288d93a1ef02025..d7df992a94be3d17d0a19ec52bbf35aad104c500 100644
--- a/test/workers/repository/process/lookup/__snapshots__/index.spec.js.snap
+++ b/test/workers/repository/process/lookup/__snapshots__/index.spec.js.snap
@@ -201,7 +201,7 @@ exports[`workers/repository/process/lookup .lookupUpdates() handles packagist 1`
 
 exports[`workers/repository/process/lookup .lookupUpdates() handles pypi 404 1`] = `Array []`;
 
-exports[`workers/repository/process/lookup .lookupUpdates() handles unknown purl 1`] = `Array []`;
+exports[`workers/repository/process/lookup .lookupUpdates() handles unknown datasource 1`] = `Array []`;
 
 exports[`workers/repository/process/lookup .lookupUpdates() ignores deprecated 1`] = `
 Object {
diff --git a/test/workers/repository/process/lookup/index.spec.js b/test/workers/repository/process/lookup/index.spec.js
index b7e3c72ebd066bcbcad10f9440ec9156ea94410e..416b225c2a27b07f52c3ac8bbcc960d35f4e2d53 100644
--- a/test/workers/repository/process/lookup/index.spec.js
+++ b/test/workers/repository/process/lookup/index.spec.js
@@ -29,7 +29,7 @@ describe('workers/repository/process/lookup', () => {
     it('returns rollback for pinned version', async () => {
       config.currentValue = '0.9.99';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       config.rollbackPrs = true;
       nock('https://registry.npmjs.org')
         .get('/q')
@@ -39,7 +39,7 @@ describe('workers/repository/process/lookup', () => {
     it('returns rollback for ranged version', async () => {
       config.currentValue = '^0.9.99';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       config.rollbackPrs = true;
       nock('https://registry.npmjs.org')
         .get('/q')
@@ -50,7 +50,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '^0.4.0';
       config.rangeStrategy = 'pin';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -60,7 +60,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '^0.4.0';
       config.rangeStrategy = 'lockfile-update';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       config.lockedVersion = '0.4.0';
       nock('https://registry.npmjs.org')
         .get('/q')
@@ -72,7 +72,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '0.4.0';
       config.rangeStrategy = 'pin';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -86,7 +86,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'pin';
       config.depName = 'q';
       config.separateMinorPatch = true;
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -100,7 +100,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'pin';
       config.separateMajorMinor = false;
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -113,7 +113,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '0.4.0';
       config.rangeStrategy = 'pin';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -126,7 +126,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '^0.4.0';
       config.rangeStrategy = 'pin';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -137,7 +137,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '^0.4.0';
       config.rangeStrategy = 'pin';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -147,7 +147,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '0.4.0';
       config.allowedVersions = '<1';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -157,7 +157,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '0.4.0';
       config.allowedVersions = '<1';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       config.versionScheme = 'docker'; // this doesn't make sense but works for this test
       nock('https://registry.npmjs.org')
         .get('/q')
@@ -168,7 +168,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '0.4.0';
       config.allowedVersions = 'less than 1';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -178,7 +178,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '0.9.0';
       config.rangeStrategy = 'pin';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -195,7 +195,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '0.9.0';
       config.rangeStrategy = 'pin';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -213,7 +213,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '0.9.0';
       config.rangeStrategy = 'pin';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -226,7 +226,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '0.9.0';
       config.rangeStrategy = 'pin';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -237,7 +237,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '0.8.0';
       config.rangeStrategy = 'pin';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -250,7 +250,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '^0.4.0';
       config.rangeStrategy = 'pin';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -261,7 +261,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '1.0.0';
       config.rangeStrategy = 'pin';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -271,7 +271,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '~0.4.0';
       config.rangeStrategy = 'pin';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -281,7 +281,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '~0.9.0';
       config.rangeStrategy = 'pin';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -291,7 +291,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '~1.0.0';
       config.rangeStrategy = 'pin';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -301,7 +301,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '~1.3.0';
       config.rangeStrategy = 'widen';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -311,7 +311,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '~1.2.0 || ~1.3.0';
       config.rangeStrategy = 'replace';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -321,7 +321,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '^2.0.0';
       config.rangeStrategy = 'widen';
       config.depName = 'webpack';
-      config.purl = 'pkg:npm/webpack';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/webpack')
         .reply(200, webpackJson);
@@ -331,7 +331,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '^1.0.0 || ^2.0.0';
       config.rangeStrategy = 'replace';
       config.depName = 'webpack';
-      config.purl = 'pkg:npm/webpack';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/webpack')
         .reply(200, webpackJson);
@@ -341,7 +341,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '^1.0.0';
       config.rangeStrategy = 'pin';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -352,7 +352,7 @@ describe('workers/repository/process/lookup', () => {
       config.lockedVersion = '1.0.0';
       config.rangeStrategy = 'pin';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -362,7 +362,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'replace';
       config.currentValue = '^1.0.0';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -372,7 +372,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'pin';
       config.currentValue = '~1.3.0';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -382,7 +382,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '1.3.x';
       config.rangeStrategy = 'pin';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -392,7 +392,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'replace';
       config.currentValue = '~1.3.0';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -402,7 +402,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'replace';
       config.currentValue = '0.x';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -412,7 +412,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'replace';
       config.currentValue = '1.3.x';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -422,7 +422,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'widen';
       config.currentValue = '1.2.x - 1.3.x';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -432,7 +432,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'replace';
       config.currentValue = '0';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -442,7 +442,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'replace';
       config.currentValue = '1.3';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -452,7 +452,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'replace';
       config.currentValue = '~0.7.0';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -462,7 +462,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'replace';
       config.currentValue = '^0.7.0';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -472,7 +472,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'widen';
       config.currentValue = '^0.7.0 || ^0.8.0';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -484,7 +484,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'widen';
       config.currentValue = '^1.0.0 || ^2.0.0';
       config.depName = 'webpack';
-      config.purl = 'pkg:npm/webpack';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/webpack')
         .reply(200, webpackJson);
@@ -494,7 +494,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'widen';
       config.currentValue = '1.x - 2.x';
       config.depName = 'webpack';
-      config.purl = 'pkg:npm/webpack';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/webpack')
         .reply(200, webpackJson);
@@ -504,7 +504,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'widen';
       config.currentValue = '1.x || 2.x';
       config.depName = 'webpack';
-      config.purl = 'pkg:npm/webpack';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/webpack')
         .reply(200, webpackJson);
@@ -514,7 +514,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'widen';
       config.currentValue = '1 || 2';
       config.depName = 'webpack';
-      config.purl = 'pkg:npm/webpack';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/webpack')
         .reply(200, webpackJson);
@@ -524,7 +524,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'widen';
       config.currentValue = '~1.2.0 || ~1.3.0';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -534,7 +534,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'replace';
       config.currentValue = '>= 0.7.0';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -544,7 +544,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'replace';
       config.currentValue = '<= 0.7.2';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -554,7 +554,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'replace';
       config.currentValue = '< 0.7.2';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -564,7 +564,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'replace';
       config.currentValue = '< 1';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -574,7 +574,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'replace';
       config.currentValue = '<= 1.3';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -585,7 +585,7 @@ describe('workers/repository/process/lookup', () => {
       config.respectLatest = false;
       config.currentValue = '<= 1';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -595,7 +595,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'replace';
       config.currentValue = '<= 1.0.0';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -607,7 +607,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'replace';
       config.currentValue = '< 1.0.0';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -619,7 +619,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'widen';
       config.currentValue = '>= 0.5.0 < 1.0.0';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -631,7 +631,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'widen';
       config.currentValue = '>= 0.5.0 <0.8';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -644,7 +644,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'widen';
       config.currentValue = '>= 0.5.0 <= 0.8.0';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -657,7 +657,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'widen';
       config.currentValue = '<= 0.8.0 >= 0.5.0';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -668,7 +668,7 @@ describe('workers/repository/process/lookup', () => {
       config.respectLatest = false;
       config.currentValue = '1.4.1';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -677,7 +677,7 @@ describe('workers/repository/process/lookup', () => {
     it('should ignore unstable versions if the current version is stable', async () => {
       config.currentValue = '2.5.16';
       config.depName = 'vue';
-      config.purl = 'pkg:npm/vue';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/vue')
         .reply(200, vueJson);
@@ -687,7 +687,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '2.5.16';
       config.ignoreUnstable = false;
       config.depName = 'vue';
-      config.purl = 'pkg:npm/vue';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/vue')
         .reply(200, vueJson);
@@ -699,7 +699,7 @@ describe('workers/repository/process/lookup', () => {
     it('should allow unstable versions if the current version is unstable', async () => {
       config.currentValue = '3.1.0-dev.20180731';
       config.depName = 'typescript';
-      config.purl = 'pkg:npm/typescript';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/typescript')
         .reply(200, typescriptJson);
@@ -711,7 +711,7 @@ describe('workers/repository/process/lookup', () => {
     it('should not jump unstable versions', async () => {
       config.currentValue = '3.0.1-insiders.20180726';
       config.depName = 'typescript';
-      config.purl = 'pkg:npm/typescript';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/typescript')
         .reply(200, typescriptJson);
@@ -723,7 +723,7 @@ describe('workers/repository/process/lookup', () => {
     it('should follow dist-tag even if newer version exists', async () => {
       config.currentValue = '3.0.1-insiders.20180713';
       config.depName = 'typescript';
-      config.purl = 'pkg:npm/typescript';
+      config.datasource = 'npm';
       config.followTag = 'insiders';
       nock('https://registry.npmjs.org')
         .get('/typescript')
@@ -736,7 +736,7 @@ describe('workers/repository/process/lookup', () => {
     it('should roll back to dist-tag if current version is higher', async () => {
       config.currentValue = '3.1.0-dev.20180813';
       config.depName = 'typescript';
-      config.purl = 'pkg:npm/typescript';
+      config.datasource = 'npm';
       config.followTag = 'insiders';
       config.rollbackPrs = true;
       nock('https://registry.npmjs.org')
@@ -750,7 +750,7 @@ describe('workers/repository/process/lookup', () => {
     it('should jump unstable versions if followTag', async () => {
       config.currentValue = '3.0.0-insiders.20180706';
       config.depName = 'typescript';
-      config.purl = 'pkg:npm/typescript';
+      config.datasource = 'npm';
       config.followTag = 'insiders';
       nock('https://registry.npmjs.org')
         .get('/typescript')
@@ -763,7 +763,7 @@ describe('workers/repository/process/lookup', () => {
     it('should update nothing if current version is dist-tag', async () => {
       config.currentValue = '3.0.1-insiders.20180726';
       config.depName = 'typescript';
-      config.purl = 'pkg:npm/typescript';
+      config.datasource = 'npm';
       config.followTag = 'insiders';
       nock('https://registry.npmjs.org')
         .get('/typescript')
@@ -774,7 +774,7 @@ describe('workers/repository/process/lookup', () => {
     it('should warn if no version matches dist-tag', async () => {
       config.currentValue = '3.0.1-dev.20180726';
       config.depName = 'typescript';
-      config.purl = 'pkg:npm/typescript';
+      config.datasource = 'npm';
       config.followTag = 'foo';
       nock('https://registry.npmjs.org')
         .get('/typescript')
@@ -791,7 +791,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'replace';
       config.currentValue = '~0.0.34';
       config.depName = '@types/helmet';
-      config.purl = 'pkg:npm/%40types/helmet';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/@types%2Fhelmet')
         .reply(200, helmetJson);
@@ -801,7 +801,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'replace';
       config.currentValue = '^0.0.34';
       config.depName = '@types/helmet';
-      config.purl = 'pkg:npm/%40types/helmet';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/@types%2Fhelmet')
         .reply(200, helmetJson);
@@ -810,7 +810,7 @@ describe('workers/repository/process/lookup', () => {
     it('should downgrade from missing versions', async () => {
       config.currentValue = '1.16.1';
       config.depName = 'coffeelint';
-      config.purl = 'pkg:npm/coffeelint';
+      config.datasource = 'npm';
       config.rollbackPrs = true;
       nock('https://registry.npmjs.org')
         .get('/coffeelint')
@@ -822,7 +822,7 @@ describe('workers/repository/process/lookup', () => {
     it('should upgrade to only one major', async () => {
       config.currentValue = '1.0.0';
       config.depName = 'webpack';
-      config.purl = 'pkg:npm/webpack';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/webpack')
         .reply(200, webpackJson);
@@ -833,7 +833,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '1.0.0';
       config.separateMultipleMajor = true;
       config.depName = 'webpack';
-      config.purl = 'pkg:npm/webpack';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/webpack')
         .reply(200, webpackJson);
@@ -844,7 +844,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '^4.4.0-canary.3';
       config.rangeStrategy = 'replace';
       config.depName = 'next';
-      config.purl = 'pkg:npm/next';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/next')
         .reply(200, nextJson);
@@ -855,7 +855,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'bump';
       config.currentValue = '^1.0.0';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -865,7 +865,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'bump';
       config.currentValue = '~1.0.0';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -876,7 +876,7 @@ describe('workers/repository/process/lookup', () => {
       config.currentValue = '~1.0.0';
       config.depName = 'q';
       config.separateMinorPatch = true;
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -886,7 +886,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'bump';
       config.currentValue = '>=1.0.0';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -896,7 +896,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'bump';
       config.currentValue = '>=0.9.0';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -906,7 +906,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'bump';
       config.currentValue = '>1.0.0';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -916,7 +916,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'bump';
       config.currentValue = '1.x';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -926,7 +926,7 @@ describe('workers/repository/process/lookup', () => {
       config.rangeStrategy = 'bump';
       config.currentValue = '^0.9.0 || ^1.0.0';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -934,7 +934,7 @@ describe('workers/repository/process/lookup', () => {
     });
     it('replaces non-range in-range updates', async () => {
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       config.packageFile = 'package.json';
       config.rangeStrategy = 'bump';
       config.currentValue = '1.0.0';
@@ -945,7 +945,7 @@ describe('workers/repository/process/lookup', () => {
     });
     it('handles github 404', async () => {
       config.depName = 'foo';
-      config.purl = 'pkg:github/some/repo';
+      config.datasource = 'github';
       config.packageFile = 'package.json';
       config.currentValue = '1.0.0';
       nock('https://pypi.org')
@@ -955,7 +955,7 @@ describe('workers/repository/process/lookup', () => {
     });
     it('handles pypi 404', async () => {
       config.depName = 'foo';
-      config.purl = 'pkg:pypi/foo';
+      config.datasource = 'pypi';
       config.packageFile = 'requirements.txt';
       config.currentValue = '1.0.0';
       nock('https://api.github.com')
@@ -965,7 +965,7 @@ describe('workers/repository/process/lookup', () => {
     });
     it('handles packagist', async () => {
       config.depName = 'foo/bar';
-      config.purl = 'pkg:packagist/foo/bar';
+      config.datasource = 'packagist';
       config.packageFile = 'composer.json';
       config.currentValue = '1.0.0';
       nock('https://packagist.org')
@@ -973,9 +973,9 @@ describe('workers/repository/process/lookup', () => {
         .reply(404);
       expect((await lookup.lookupUpdates(config)).updates).toMatchSnapshot();
     });
-    it('handles unknown purl', async () => {
+    it('handles unknown datasource', async () => {
       config.depName = 'foo';
-      config.purl = 'pkg:typo/some/repo';
+      config.datasource = 'typo';
       config.packageFile = 'package.json';
       config.currentValue = '1.0.0';
       expect((await lookup.lookupUpdates(config)).updates).toMatchSnapshot();
@@ -987,8 +987,8 @@ describe('workers/repository/process/lookup', () => {
       config.lockedVersion = '0.9.4';
       config.currentValue = '~=0.9';
       config.depName = 'q';
-      // TODO: we are using npm as source, since purl for pypi is not implimented
-      config.purl = 'pkg:npm/q';
+      // TODO: we are using npm as source to test pep440
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -998,7 +998,7 @@ describe('workers/repository/process/lookup', () => {
     it('returns complex object', async () => {
       config.currentValue = '1.3.0';
       config.depName = 'q';
-      config.purl = 'pkg:npm/q';
+      config.datasource = 'npm';
       nock('https://registry.npmjs.org')
         .get('/q')
         .reply(200, qJson);
@@ -1010,7 +1010,7 @@ describe('workers/repository/process/lookup', () => {
     it('ignores deprecated', async () => {
       config.currentValue = '1.3.0';
       config.depName = 'q2';
-      config.purl = 'pkg:npm/q2';
+      config.datasource = 'npm';
       const returnJson = JSON.parse(JSON.stringify(qJson));
       returnJson.name = 'q2';
       returnJson.versions['1.4.1'].deprecated = 'true';
@@ -1025,20 +1025,20 @@ describe('workers/repository/process/lookup', () => {
     it('skips unsupported values', async () => {
       config.currentValue = 'alpine';
       config.depName = 'node';
-      config.purl = 'pkg:docker/node';
+      config.datasource = 'docker';
       const res = await lookup.lookupUpdates(config);
       expect(res).toMatchSnapshot();
     });
     it('skips undefined values', async () => {
       config.depName = 'node';
-      config.purl = 'pkg:docker/node';
+      config.datasource = 'docker';
       const res = await lookup.lookupUpdates(config);
       expect(res).toMatchSnapshot();
     });
     it('handles digest pin', async () => {
       config.currentValue = '8.0.0';
       config.depName = 'node';
-      config.purl = 'pkg:docker/node';
+      config.datasource = 'docker';
       config.pinDigests = true;
       docker.getPkgReleases.mockReturnValueOnce({
         releases: [
@@ -1059,7 +1059,7 @@ describe('workers/repository/process/lookup', () => {
       it('skips uncompatible versions for ' + currentValue, async () => {
         config.currentValue = currentValue;
         config.depName = 'node';
-        config.purl = 'pkg:docker/node';
+        config.datasource = 'docker';
         config.versionScheme = 'docker';
         docker.getPkgReleases.mockReturnValueOnce({
           releases: [
@@ -1081,7 +1081,7 @@ describe('workers/repository/process/lookup', () => {
     it('handles digest pin for up to date version', async () => {
       config.currentValue = '8.1.0';
       config.depName = 'node';
-      config.purl = 'pkg:docker/node';
+      config.datasource = 'docker';
       config.pinDigests = true;
       docker.getPkgReleases.mockReturnValueOnce({
         releases: [
@@ -1100,7 +1100,7 @@ describe('workers/repository/process/lookup', () => {
     it('handles digest pin for non-version', async () => {
       config.currentValue = 'alpine';
       config.depName = 'node';
-      config.purl = 'pkg:docker/node';
+      config.datasource = 'docker';
       config.pinDigests = true;
       docker.getPkgReleases.mockReturnValueOnce({
         releases: [
@@ -1122,7 +1122,7 @@ describe('workers/repository/process/lookup', () => {
     it('handles digest lookup failure', async () => {
       config.currentValue = 'alpine';
       config.depName = 'node';
-      config.purl = 'pkg:docker/node';
+      config.datasource = 'docker';
       config.pinDigests = true;
       docker.getPkgReleases.mockReturnValueOnce({
         releases: [
@@ -1144,7 +1144,7 @@ describe('workers/repository/process/lookup', () => {
     it('handles digest update', async () => {
       config.currentValue = '8.0.0';
       config.depName = 'node';
-      config.purl = 'pkg:docker/node';
+      config.datasource = 'docker';
       config.currentDigest = 'sha256:zzzzzzzzzzzzzzz';
       config.pinDigests = true;
       docker.getPkgReleases.mockReturnValueOnce({
@@ -1165,7 +1165,7 @@ describe('workers/repository/process/lookup', () => {
     it('handles digest update for non-version', async () => {
       config.currentValue = 'alpine';
       config.depName = 'node';
-      config.purl = 'pkg:docker/node';
+      config.datasource = 'docker';
       config.currentDigest = 'sha256:zzzzzzzzzzzzzzz';
       config.pinDigests = true;
       docker.getPkgReleases.mockReturnValueOnce({