]>
git.scottworley.com Git - nix-pin-deps/blob - nix_pin_deps.py
20988f58289b8a002c40f6c1a16d9c242a6357aa
1 from contextlib
import contextmanager
12 print(msg
, file=sys
.stderr
, end
='', flush
=True)
16 print('\r', file=sys
.stderr
, end
='', flush
=True)
19 class ParseNixStoreQueryGraphML(xml
.sax
.handler
.ContentHandler
):
22 self
.non_roots
= set()
25 def startElement(self
, name
, attrs
):
27 source
= attrs
.getValue("source")
28 target
= attrs
.getValue("target")
29 self
.non_roots
.add(target
)
30 self
.deps
.setdefault(source
, []).append(target
)
31 if target
in self
.roots
:
32 self
.roots
.remove(target
)
33 if source
not in self
.non_roots
:
34 self
.roots
.add(source
)
38 with log("Loading dependency tree..."):
39 process
= subprocess
.Popen(
40 ["nix-store", "--query", "--graphml", drv
], stdout
=subprocess
.PIPE
)
41 parser
= ParseNixStoreQueryGraphML()
42 xml
.sax
.parse(process
.stdout
, parser
)
43 assert process
.wait() == 0
48 with log("Loading %s..." % drv
):
49 process
= subprocess
.Popen(["nix",
50 "--experimental-features",
54 stdout
=subprocess
.PIPE
)
55 info
= json
.load(process
.stdout
)
56 assert process
.wait() == 0
61 # TODO: How to pin outputs one at a time?
62 # Currently, we only pin when all outputs are available.
63 # It would be better to pin the outputs we've got.
64 return all(os
.path
.exists(o
['path']) for d
in getDrvInfo(
65 drv
).values() for o
in d
['outputs'].values())
69 return thing
.endswith(".drv")
72 def removesuffix(s
, suf
):
73 return s
[:-len(suf
)] if s
.endswith(suf
) else s
77 outPath
= os
.path
.join(sys
.argv
[2], removesuffix(drv
, ".drv"))
78 if not os
.path
.exists(outPath
):
79 process
= subprocess
.run(["nix-store",
87 def pinBuiltThings(thing
, done
, deps
):
91 if not isDrv(thing
) or allBuilt(thing
):
94 for dep
in deps
.get(thing
, []):
95 pinBuiltThings(dep
, done
, deps
)
98 dep_graph
= getDeps(sys
.argv
[1])
99 for root
in dep_graph
.roots
:
100 pinBuiltThings(root
, set(), dep_graph
.deps
)