aboutsummaryrefslogtreecommitdiff
#include "misc.hh"
#include "store-api.hh"
#include "local-store.hh"
#include "globals.hh"


namespace nix {


Derivation derivationFromPath(StoreAPI & store, const Path & drvPath)
{
    assertStorePath(drvPath);
    store.ensurePath(drvPath);
    return readDerivation(drvPath);
}


void computeFSClosure(StoreAPI & store, const Path & path,
    PathSet & paths, bool flipDirection, bool includeOutputs, bool includeDerivers)
{
    if (paths.find(path) != paths.end()) return;
    paths.insert(path);

    PathSet edges;

    if (flipDirection) {
        store.queryReferrers(path, edges);

        if (includeOutputs) {
            PathSet derivers = store.queryValidDerivers(path);
            foreach (PathSet::iterator, i, derivers)
                edges.insert(*i);
        }

        if (includeDerivers && isDerivation(path)) {
            PathSet outputs = store.queryDerivationOutputs(path);
            foreach (PathSet::iterator, i, outputs)
                if (store.isValidPath(*i) && store.queryDeriver(*i) == path)
                    edges.insert(*i);
        }

    } else {
        store.queryReferences(path, edges);

        if (includeOutputs && isDerivation(path)) {
            PathSet outputs = store.queryDerivationOutputs(path);
            foreach (PathSet::iterator, i, outputs)
                if (store.isValidPath(*i)) edges.insert(*i);
        }

        if (includeDerivers) {
            Path deriver = store.queryDeriver(path);
            if (store.isValidPath(deriver)) edges.insert(deriver);
        }
    }

    foreach (PathSet::iterator, i, edges)
        computeFSClosure(store, *i, paths, flipDirection, includeOutputs, includeDerivers);
}


static void dfsVisit(StoreAPI & store, const PathSet & paths,
    const Path & path, PathSet & visited, Paths & sorted,
    PathSet & parents)
{
    if (parents.find(path) != parents.end())
        throw BuildError(format("cycle detected in the references of `%1%'") % path);

    if (visited.find(path) != visited.end()) return;
    visited.insert(path);
    parents.insert(path);

    PathSet references;
    if (store.isValidPath(path))
        store.queryReferences(path, references);

    foreach (PathSet::iterator, i, references)
        /* Don't traverse into paths that don't exist.  That can
           happen due to substitutes for non-existent paths. */
        if (*i != path && paths.find(*i) != paths.end())
            dfsVisit(store, paths, *i, visited, sorted, parents);

    sorted.push_front(path);
    parents.erase(path);
}


Paths topoSortPaths(StoreAPI & store, const PathSet & paths)
{
    Paths sorted;
    PathSet visited, parents;
    foreach (PathSet::const_iterator, i, paths)
        dfsVisit(store, paths, *i, visited, sorted, parents);
    return sorted;
}


}
aim@flashner.co.il> Björn Höfling 2020-11-30gnu: gpxsee: Update to 7.37....* gnu/packages/gps.scm (gpxsee): Update to 7.37. Tobias Geerinckx-Rice 2020-11-29gnu: gama: Update to 2.12....* gnu/packages/gps.scm (gama): Update to 2.12. Efraim Flashner 2020-11-13gnu: gpxsee: Update to 7.36....* gnu/packages/gps.scm (gpxsee): Update to 7.36. Tobias Geerinckx-Rice 2020-11-05gnu: gpxsee: Update to 7.35....* gnu/packages/gps.scm (gpxsee): Update to 7.35. Tobias Geerinckx-Rice 2020-10-28gnu: gama: Remove bundled library....* gnu/packages/gps.scm (gama)[source]: Add snippet to remove bundled expat-1.1 library. Efraim Flashner 2020-10-28gnu: gama: Update to 2.11....* gnu/packages/gps.scm (gama): Update to 2.11. Efraim Flashner 2020-10-16gnu: gpxsee: Update to 7.34....* gnu/packages/gps.scm (gpxsee): Update to 7.34. Tobias Geerinckx-Rice 2020-09-27gnu: gama: Update to 2.10....* gnu/packages/gps.scm (gama): Update to 2.10. Efraim Flashner 2020-08-16gnu: gpsd: Update to 3.21....* gnu/packages/gps.scm (gpsd): Update to 3.21. Tobias Geerinckx-Rice