25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

447 lines
19 KiB

Fix handling of transient locks during upgrade We currently have a problem in the handling of locks in the `upgrade <app>` command when a transitive dependency switches supervision trees. If we start with: A / \ B1 C | D | E And upgrade to: A / \ B2 C | | E D by calling `rebar3 upgrade b`, we would expect the ugprade command to do so directly. However we are currently left with the following lock file: A / \ B2 C | D | E This is _not_ critical since on the next run, the lock file is fixed automatically through an install-deps sequence. However, this is a jarring state in which to leave a project. The reason is that we proceed the following way to handle an upgrade: 1. pick the name of the chosen app, and unlock it if it's at the level 0 2. grab a list of all its current children (and their own) and unlock them 3. do the same for all the other unlocked dependencies 4. pass this new lock internal format to the get-deps provider in upgrade mode 5. take the result and save it to the lock file. What's interesting is that right now this yields invalid locks at step 3, because we have removed the lock on B1, but not on E (which we don't yet know is going to be a new child of the next B version until we fetch it) In step 4, we fetch dependencies, and in there we compare the pre-upgrade locks and fetch structure with those expected in the current lock state, and rebuild everything. The fix in this commit adds a check there where if the app is in the current lock set at a level deeper than the current one, the lock is forced to be refreshed as if it were not there. This lock would get refreshed on a blank run anyway since the current lock set would start empty (rather than pre-populated by `upgrade`), and the level-order traversal ensures that the locks remain safe in all cases. Fixes #2030
6 년 전
Fix handling of transient locks during upgrade We currently have a problem in the handling of locks in the `upgrade <app>` command when a transitive dependency switches supervision trees. If we start with: A / \ B1 C | D | E And upgrade to: A / \ B2 C | | E D by calling `rebar3 upgrade b`, we would expect the ugprade command to do so directly. However we are currently left with the following lock file: A / \ B2 C | D | E This is _not_ critical since on the next run, the lock file is fixed automatically through an install-deps sequence. However, this is a jarring state in which to leave a project. The reason is that we proceed the following way to handle an upgrade: 1. pick the name of the chosen app, and unlock it if it's at the level 0 2. grab a list of all its current children (and their own) and unlock them 3. do the same for all the other unlocked dependencies 4. pass this new lock internal format to the get-deps provider in upgrade mode 5. take the result and save it to the lock file. What's interesting is that right now this yields invalid locks at step 3, because we have removed the lock on B1, but not on E (which we don't yet know is going to be a new child of the next B version until we fetch it) In step 4, we fetch dependencies, and in there we compare the pre-upgrade locks and fetch structure with those expected in the current lock state, and rebuild everything. The fix in this commit adds a check there where if the app is in the current lock set at a level deeper than the current one, the lock is forced to be refreshed as if it were not there. This lock would get refreshed on a blank run anyway since the current lock set would start empty (rather than pre-populated by `upgrade`), and the level-order traversal ensures that the locks remain safe in all cases. Fixes #2030
6 년 전
Fix handling of transient locks during upgrade We currently have a problem in the handling of locks in the `upgrade <app>` command when a transitive dependency switches supervision trees. If we start with: A / \ B1 C | D | E And upgrade to: A / \ B2 C | | E D by calling `rebar3 upgrade b`, we would expect the ugprade command to do so directly. However we are currently left with the following lock file: A / \ B2 C | D | E This is _not_ critical since on the next run, the lock file is fixed automatically through an install-deps sequence. However, this is a jarring state in which to leave a project. The reason is that we proceed the following way to handle an upgrade: 1. pick the name of the chosen app, and unlock it if it's at the level 0 2. grab a list of all its current children (and their own) and unlock them 3. do the same for all the other unlocked dependencies 4. pass this new lock internal format to the get-deps provider in upgrade mode 5. take the result and save it to the lock file. What's interesting is that right now this yields invalid locks at step 3, because we have removed the lock on B1, but not on E (which we don't yet know is going to be a new child of the next B version until we fetch it) In step 4, we fetch dependencies, and in there we compare the pre-upgrade locks and fetch structure with those expected in the current lock state, and rebuild everything. The fix in this commit adds a check there where if the app is in the current lock set at a level deeper than the current one, the lock is forced to be refreshed as if it were not there. This lock would get refreshed on a blank run anyway since the current lock set would start empty (rather than pre-populated by `upgrade`), and the level-order traversal ensures that the locks remain safe in all cases. Fixes #2030
6 년 전
9 년 전
support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 년 전
9 년 전
9 년 전
support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 년 전
9 년 전
support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 년 전
support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 년 전
support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 년 전
support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 년 전
support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 년 전
support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 년 전
support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 년 전
support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 년 전
support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 년 전
support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 년 전
support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 년 전
support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 년 전
support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 년 전
support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message
6 년 전
Fix handling of transient locks during upgrade We currently have a problem in the handling of locks in the `upgrade <app>` command when a transitive dependency switches supervision trees. If we start with: A / \ B1 C | D | E And upgrade to: A / \ B2 C | | E D by calling `rebar3 upgrade b`, we would expect the ugprade command to do so directly. However we are currently left with the following lock file: A / \ B2 C | D | E This is _not_ critical since on the next run, the lock file is fixed automatically through an install-deps sequence. However, this is a jarring state in which to leave a project. The reason is that we proceed the following way to handle an upgrade: 1. pick the name of the chosen app, and unlock it if it's at the level 0 2. grab a list of all its current children (and their own) and unlock them 3. do the same for all the other unlocked dependencies 4. pass this new lock internal format to the get-deps provider in upgrade mode 5. take the result and save it to the lock file. What's interesting is that right now this yields invalid locks at step 3, because we have removed the lock on B1, but not on E (which we don't yet know is going to be a new child of the next B version until we fetch it) In step 4, we fetch dependencies, and in there we compare the pre-upgrade locks and fetch structure with those expected in the current lock state, and rebuild everything. The fix in this commit adds a check there where if the app is in the current lock set at a level deeper than the current one, the lock is forced to be refreshed as if it were not there. This lock would get refreshed on a blank run anyway since the current lock set would start empty (rather than pre-populated by `upgrade`), and the level-order traversal ensures that the locks remain safe in all cases. Fixes #2030
6 년 전
  1. %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
  2. %% ex: ts=4 sw=4 et
  3. %% -------------------------------------------------------------------
  4. %%
  5. %% rebar: Erlang Build Tools
  6. %%
  7. %% Copyright (c) 2009 Dave Smith (dizzyd@dizzyd.com)
  8. %%
  9. %% Permission is hereby granted, free of charge, to any person obtaining a copy
  10. %% of this software and associated documentation files (the "Software"), to deal
  11. %% in the Software without restriction, including without limitation the rights
  12. %% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. %% copies of the Software, and to permit persons to whom the Software is
  14. %% furnished to do so, subject to the following conditions:
  15. %%
  16. %% The above copyright notice and this permission notice shall be included in
  17. %% all copies or substantial portions of the Software.
  18. %%
  19. %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. %% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. %% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. %% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. %% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. %% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. %% THE SOFTWARE.
  26. %% -------------------------------------------------------------------
  27. -module(rebar_prv_install_deps).
  28. -behaviour(provider).
  29. -export([init/1,
  30. do/1,
  31. format_error/1]).
  32. -include("rebar.hrl").
  33. -include_lib("providers/include/providers.hrl").
  34. -export([do_/1,
  35. handle_deps_as_profile/4,
  36. profile_dep_dir/2,
  37. find_cycles/1,
  38. cull_compile/2]).
  39. -export_type([dep/0]).
  40. -define(PROVIDER, install_deps).
  41. -define(DEPS, [app_discovery]).
  42. -type src_dep() :: {atom(), {atom(), string(), string()}}
  43. | {atom(), string(), {atom(), string(), string()}}.
  44. -type pkg_dep() :: {atom(), binary()} | atom().
  45. -type dep() :: src_dep() | pkg_dep().
  46. %% ===================================================================
  47. %% Public API
  48. %% ===================================================================
  49. -spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
  50. init(State) ->
  51. State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
  52. {module, ?MODULE},
  53. {bare, false},
  54. {deps, ?DEPS},
  55. {example, undefined},
  56. {short_desc, ""},
  57. {desc, ""},
  58. {opts, []}])),
  59. {ok, State1}.
  60. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
  61. do(State) ->
  62. ?INFO("Verifying dependencies...", []),
  63. do_(State).
  64. do_(State) ->
  65. try
  66. Profiles = rebar_state:current_profiles(State),
  67. ProjectApps = rebar_state:project_apps(State),
  68. Upgrade = rebar_state:get(State, upgrade, false),
  69. {Apps, State1} = deps_per_profile(Profiles, Upgrade, State),
  70. State2 = rebar_state:update_all_deps(State1, Apps),
  71. CodePaths = [rebar_app_info:ebin_dir(A) || A <- Apps],
  72. State3 = rebar_state:update_code_paths(State2, all_deps, CodePaths),
  73. Source = ProjectApps ++ Apps,
  74. case find_cycles(Source) of
  75. {cycles, Cycles} ->
  76. ?PRV_ERROR({cycles, Cycles});
  77. {error, Error} ->
  78. {error, Error};
  79. {no_cycle, Sorted} ->
  80. ToCompile = cull_compile(Sorted, ProjectApps),
  81. {ok, rebar_state:deps_to_build(State3, ToCompile)}
  82. end
  83. catch
  84. %% maybe_fetch will maybe_throw an exception to break out of some loops
  85. _:{error, Reason} ->
  86. {error, Reason}
  87. end.
  88. %% @doc convert a given exception's payload into an io description.
  89. -spec format_error(any()) -> iolist().
  90. format_error({dep_app_not_found, AppDir, AppName}) ->
  91. io_lib:format("Dependency failure: Application ~ts not found at the top level of directory ~ts", [AppName, AppDir]);
  92. format_error({load_registry_fail, Dep}) ->
  93. io_lib:format("Error loading registry to resolve version of ~ts. Try fixing by running 'rebar3 update'", [Dep]);
  94. format_error({bad_constraint, Name, Constraint}) ->
  95. io_lib:format("Unable to parse version for package ~ts: ~ts", [Name, Constraint]);
  96. format_error({parse_dep, Dep}) ->
  97. io_lib:format("Failed parsing dep ~p", [Dep]);
  98. format_error({not_rebar_package, Package, Version}) ->
  99. io_lib:format("Package not buildable with rebar3: ~ts-~ts", [Package, Version]);
  100. format_error({missing_package, Package, Version}) ->
  101. io_lib:format("Package not found in registry: ~ts-~ts", [Package, Version]);
  102. format_error({missing_package, Package}) ->
  103. io_lib:format("Package not found in registry: ~ts", [Package]);
  104. format_error({cycles, Cycles}) ->
  105. Prints = [["applications: ",
  106. [io_lib:format("~ts ", [Dep]) || Dep <- Cycle],
  107. "depend on each other\n"]
  108. || Cycle <- Cycles],
  109. ["Dependency cycle(s) detected:\n", Prints];
  110. format_error(Reason) ->
  111. io_lib:format("~p", [Reason]).
  112. %% @doc Allows other providers to install deps in a given profile
  113. %% manually, outside of what is provided by rebar3's deps tuple.
  114. -spec handle_deps_as_profile(Profile, State, Deps, Upgrade) -> {Apps, State} when
  115. Profile :: atom(),
  116. State :: rebar_state:t(),
  117. Deps :: [tuple() | atom() | binary()], % TODO: meta to source() | lock()
  118. Upgrade :: boolean(),
  119. Apps :: [rebar_app_info:t()].
  120. handle_deps_as_profile(Profile, State, Deps, Upgrade) ->
  121. Locks = [],
  122. Level = 0,
  123. DepsDir = profile_dep_dir(State, Profile),
  124. Deps1 = rebar_app_utils:parse_deps(DepsDir, Deps, State, Locks, Level),
  125. ProfileLevelDeps = [{Profile, Deps1, Level}],
  126. RootSeen = sets:from_list([rebar_app_info:name(AppInfo)
  127. || AppInfo <- rebar_state:project_apps(State)]),
  128. handle_profile_level(ProfileLevelDeps, [], RootSeen, RootSeen, Upgrade, Locks, State).
  129. %% ===================================================================
  130. %% Internal functions
  131. %% ===================================================================
  132. %% finds all the deps in `{deps, ...}` for each profile provided.
  133. deps_per_profile(Profiles, Upgrade, State) ->
  134. Level = 0,
  135. Locks = rebar_state:get(State, {locks, default}, []),
  136. Deps = lists:foldl(fun(Profile, DepAcc) ->
  137. [parsed_profile_deps(State, Profile, Level) | DepAcc]
  138. end, [], Profiles),
  139. RootSeen = sets:from_list([rebar_app_info:name(AppInfo)
  140. || AppInfo <- rebar_state:project_apps(State)]),
  141. handle_profile_level(Deps, [], RootSeen, RootSeen, Upgrade, Locks, State).
  142. parsed_profile_deps(State, Profile, Level) ->
  143. ParsedDeps = rebar_state:get(State, {parsed_deps, Profile}, []),
  144. {Profile, ParsedDeps, Level}.
  145. %% Level-order traversal of all dependencies, across profiles.
  146. %% If profiles x,y,z are present, then the traversal will go:
  147. %% x0, y0, z0, x1, y1, z1, ..., xN, yN, zN.
  148. %%
  149. %% There are two 'seen' sets: one for the top-level apps (`RootSeen') and
  150. %% one for all dependencies (`Seen'). The former is used to know when
  151. %% to skip the resolving of dependencies altogether (since they're already
  152. %% top-level apps), while the latter is used to prevent reprocessing
  153. %% deps more than one.
  154. handle_profile_level([], Apps, _RootSeen, _Seen, _Upgrade, _Locks, State) ->
  155. {Apps, State};
  156. handle_profile_level([{Profile, Deps, Level} | Rest], Apps, RootSeen, Seen, Upgrade, Locks, State) ->
  157. Deps0 = [rebar_app_utils:expand_deps_sources(Dep, State)
  158. || Dep <- Deps,
  159. %% skip top-level apps being double-declared
  160. not sets:is_element(rebar_app_info:name(Dep), RootSeen)],
  161. {Deps1, Apps1, State1, Seen1} =
  162. update_deps(Profile, Level, Deps0, Apps
  163. ,State, Upgrade, Seen, Locks),
  164. Deps2 = case Deps1 of
  165. [] -> Rest;
  166. _ -> Rest ++ [{Profile, Deps1, Level+1}]
  167. end,
  168. handle_profile_level(Deps2, Apps1, RootSeen, sets:union(Seen, Seen1), Upgrade, Locks, State1).
  169. find_cycles(Apps) ->
  170. case rebar_digraph:compile_order(Apps) of
  171. {error, {cycles, Cycles}} -> {cycles, Cycles};
  172. {error, Error} -> {error, Error};
  173. {ok, Sorted} -> {no_cycle, Sorted}
  174. end.
  175. cull_compile(TopSortedDeps, ProjectApps) ->
  176. lists:dropwhile(fun not_needs_compile/1, TopSortedDeps -- ProjectApps).
  177. maybe_lock(Profile, AppInfo, Seen, State, Level) ->
  178. Name = rebar_app_info:name(AppInfo),
  179. case rebar_app_info:is_checkout(AppInfo) of
  180. false ->
  181. case Profile of
  182. default ->
  183. case sets:is_element(Name, Seen) of
  184. false ->
  185. %% Check whether the currently existing lock is
  186. %% deeper than the current one (which can happen
  187. %% during an upgrade). If the current app is
  188. %% shallower than the existing lock, replace the
  189. %% existing lock. This prevents weird transient
  190. %% lock-tree states (which would self-heal on a
  191. %% later run) after a `rebar3 upgrade <app>'
  192. %% command when a deep dep switches lineages for
  193. %% another newer parent.
  194. Locks = rebar_state:lock(State),
  195. case find_app_and_level_by_name(Locks, Name) of
  196. {ok, _App, LockLvl} when LockLvl =< Level ->
  197. {sets:add_element(Name, Seen), State};
  198. {ok, App, _LockLvl} ->
  199. LockedApp = rebar_app_info:dep_level(AppInfo, Level),
  200. {sets:add_element(Name, Seen),
  201. rebar_state:lock(State, [LockedApp | Locks -- [App]])};
  202. false ->
  203. {sets:add_element(Name, Seen),
  204. rebar_state:lock(State, rebar_app_info:dep_level(AppInfo, Level))}
  205. end;
  206. true ->
  207. {Seen, State}
  208. end;
  209. _ ->
  210. {sets:add_element(Name, Seen), State}
  211. end;
  212. true ->
  213. {sets:add_element(Name, Seen), State}
  214. end.
  215. update_deps(Profile, Level, Deps, Apps, State, Upgrade, Seen, Locks) ->
  216. lists:foldl(
  217. fun(AppInfo, {DepsAcc, AppsAcc, StateAcc, SeenAcc}) ->
  218. update_dep(AppInfo, Profile, Level,
  219. DepsAcc, AppsAcc, StateAcc,
  220. Upgrade, SeenAcc, Locks)
  221. end,
  222. {[], Apps, State, Seen},
  223. rebar_utils:sort_deps(Deps)).
  224. update_dep(AppInfo, Profile, Level, Deps, Apps, State, Upgrade, Seen, Locks) ->
  225. %% If not seen, add to list of locks to write out
  226. Name = rebar_app_info:name(AppInfo),
  227. case sets:is_element(Name, Seen) of
  228. true ->
  229. update_seen_dep(AppInfo, Profile, Level,
  230. Deps, Apps,
  231. State, Upgrade, Seen, Locks);
  232. false ->
  233. update_unseen_dep(AppInfo, Profile, Level,
  234. Deps, Apps,
  235. State, Upgrade, Seen, Locks)
  236. end.
  237. profile_dep_dir(State, Profile) ->
  238. case Profile of
  239. default -> filename:join([rebar_dir:profile_dir(rebar_state:opts(State), [default]), rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIR)]);
  240. _ -> rebar_dir:deps_dir(State)
  241. end.
  242. update_seen_dep(AppInfo, _Profile, _Level, Deps, Apps, State, Upgrade, Seen, Locks) ->
  243. Name = rebar_app_info:name(AppInfo),
  244. %% If seen from lock file or user requested an upgrade
  245. %% don't print warning about skipping
  246. case lists:keymember(Name, 1, Locks) of
  247. false when Upgrade ->
  248. ok;
  249. false when not Upgrade ->
  250. {ok, SeenApp} = rebar_app_utils:find(Name, Apps),
  251. Source = rebar_app_info:source(AppInfo),
  252. case rebar_app_info:source(SeenApp) of
  253. Source ->
  254. %% dep is the same version and checksum as the one we already saw.
  255. %% meaning there is no conflict, so don't warn about it.
  256. skip;
  257. _ ->
  258. warn_skip_deps(AppInfo, State)
  259. end;
  260. true ->
  261. ok
  262. end,
  263. {Deps, Apps, State, Seen}.
  264. update_unseen_dep(AppInfo, Profile, Level, Deps, Apps, State, Upgrade, Seen, Locks) ->
  265. {NewSeen, State1} = maybe_lock(Profile, AppInfo, Seen, State, Level),
  266. {_, AppInfo1} = maybe_fetch(AppInfo, Profile, Upgrade, Seen, State1),
  267. DepsDir = profile_dep_dir(State, Profile),
  268. {AppInfo2, NewDeps, State2} =
  269. handle_dep(State1, Profile, DepsDir, AppInfo1, Locks, Level),
  270. AppInfo3 = rebar_app_info:dep_level(AppInfo2, Level),
  271. {NewDeps ++ Deps, [AppInfo3 | Apps], State2, NewSeen}.
  272. -spec handle_dep(rebar_state:t(), atom(), file:filename_all(), rebar_app_info:t(), list(), integer()) -> {rebar_app_info:t(), [rebar_app_info:t()], rebar_state:t()}.
  273. handle_dep(State, Profile, DepsDir, AppInfo, Locks, Level) ->
  274. Name = rebar_app_info:name(AppInfo),
  275. AppInfo1 = rebar_app_info:apply_overrides(rebar_app_info:get(AppInfo, overrides, []), AppInfo),
  276. AppInfo2 = rebar_app_info:apply_profiles(AppInfo1, [default, prod]),
  277. Plugins = rebar_app_info:get(AppInfo2, plugins, []),
  278. AppInfo3 = rebar_app_info:set(AppInfo2, {plugins, Profile}, Plugins),
  279. %% Will throw an exception if checks fail
  280. rebar_app_info:verify_otp_vsn(AppInfo3),
  281. %% Dep may have plugins to install. Find and install here.
  282. State1 = rebar_plugins:install(State, AppInfo3),
  283. %% Upgrade lock level to be the level the dep will have in this dep tree
  284. Deps = rebar_app_info:get(AppInfo3, {deps, default}, []) ++ rebar_app_info:get(AppInfo3, {deps, prod}, []),
  285. AppInfo4 = rebar_app_info:deps(AppInfo3, rebar_state:deps_names(Deps)),
  286. %% Keep all overrides from the global config and this dep when parsing its deps
  287. Overrides = rebar_app_info:get(AppInfo, overrides, []),
  288. Deps1 = rebar_app_utils:parse_deps(Name, DepsDir, Deps, rebar_state:set(State, overrides, Overrides)
  289. ,Locks, Level+1),
  290. {AppInfo4, Deps1, State1}.
  291. -spec maybe_fetch(rebar_app_info:t(), atom(), boolean(),
  292. sets:set(binary()), rebar_state:t()) -> {ok, rebar_app_info:t()}.
  293. maybe_fetch(AppInfo, Profile, Upgrade, Seen, State) ->
  294. AppDir = rebar_utils:to_list(rebar_app_info:dir(AppInfo)),
  295. %% Don't fetch dep if it exists in the _checkouts dir
  296. case rebar_app_info:is_checkout(AppInfo) of
  297. true ->
  298. {ok, AppInfo};
  299. false ->
  300. case rebar_app_info:is_available(AppInfo) of
  301. false ->
  302. AppInfo1 = fetch_app(AppInfo, State),
  303. maybe_symlink_default(State, Profile, AppDir, AppInfo1),
  304. {ok, rebar_app_info:is_available(rebar_app_info:valid(AppInfo1, false), true)};
  305. true ->
  306. case sets:is_element(rebar_app_info:name(AppInfo), Seen) of
  307. true ->
  308. {ok, AppInfo};
  309. false ->
  310. maybe_symlink_default(State, Profile, AppDir, AppInfo),
  311. AppInfo1 = maybe_upgrade(AppInfo, AppDir, Upgrade, State),
  312. {ok, AppInfo1}
  313. end
  314. end
  315. end.
  316. needs_symlinking(State, Profile) ->
  317. case {rebar_state:current_profiles(State), Profile} of
  318. {[default], default} ->
  319. %% file will be in default already -- this is the only run we have
  320. false;
  321. {_, default} ->
  322. %% file fetched to default, needs to be linked to the current
  323. %% run's directory.
  324. true;
  325. _ ->
  326. %% File fetched to the right directory already
  327. false
  328. end.
  329. maybe_symlink_default(State, Profile, AppDir, AppInfo) ->
  330. case needs_symlinking(State, Profile) of
  331. true ->
  332. SymDir = filename:join([rebar_dir:deps_dir(State),
  333. rebar_app_info:name(AppInfo)]),
  334. symlink_dep(State, AppDir, SymDir),
  335. true;
  336. false ->
  337. false
  338. end.
  339. symlink_dep(State, From, To) ->
  340. filelib:ensure_dir(To),
  341. case rebar_file_utils:symlink_or_copy(From, To) of
  342. ok ->
  343. RelativeFrom = make_relative_to_root(State, From),
  344. RelativeTo = make_relative_to_root(State, To),
  345. ?INFO("Linking ~ts to ~ts", [RelativeFrom, RelativeTo]),
  346. ok;
  347. exists ->
  348. ok
  349. end.
  350. make_relative_to_root(State, Path) when is_binary(Path) ->
  351. make_relative_to_root(State, binary_to_list(Path));
  352. make_relative_to_root(State, Path) when is_list(Path) ->
  353. Root = rebar_dir:root_dir(State),
  354. rebar_dir:make_relative_path(Path, Root).
  355. fetch_app(AppInfo, State) ->
  356. ?INFO("Fetching ~ts", [rebar_resource_v2:format_source(AppInfo)]),
  357. rebar_fetch:download_source(AppInfo, State).
  358. maybe_upgrade(AppInfo, _AppDir, Upgrade, State) ->
  359. case Upgrade orelse rebar_app_info:is_lock(AppInfo) of
  360. true ->
  361. case rebar_fetch:needs_update(AppInfo, State) of
  362. true ->
  363. ?INFO("Upgrading ~ts", [rebar_resource_v2:format_source(AppInfo)]),
  364. rebar_fetch:download_source(AppInfo, State);
  365. false ->
  366. case Upgrade of
  367. true ->
  368. ?INFO("No upgrade needed for ~ts", [rebar_app_info:name(AppInfo)]),
  369. AppInfo;
  370. false ->
  371. AppInfo
  372. end
  373. end;
  374. false ->
  375. AppInfo
  376. end.
  377. warn_skip_deps(AppInfo, State) ->
  378. Msg = "Skipping ~ts as an app of the same name "
  379. "has already been fetched",
  380. Args = [rebar_resource_v2:format_source(AppInfo)],
  381. case rebar_state:get(State, deps_error_on_conflict, false) of
  382. false ->
  383. case rebar_state:get(State, deps_warning_on_conflict, true) of
  384. true -> ?WARN(Msg, Args);
  385. false -> ok
  386. end;
  387. true ->
  388. ?ERROR(Msg, Args), ?FAIL
  389. end.
  390. not_needs_compile(App) ->
  391. not(rebar_app_info:is_checkout(App))
  392. andalso rebar_app_info:valid(App)
  393. andalso rebar_app_info:has_all_artifacts(App) =:= true.
  394. find_app_and_level_by_name([], _) ->
  395. false;
  396. find_app_and_level_by_name([App|Apps], Name) ->
  397. case rebar_app_info:name(App) of
  398. Name -> {ok, App, rebar_app_info:dep_level(App)};
  399. _ -> find_app_and_level_by_name(Apps, Name)
  400. end.