#! @perl@ -w use strict; my $rootsDir = "@localstatedir@/nix/gcroots/channels"; # Figure out the name of the `.nix-channels' file to use. my $home = $ENV{"HOME"}; die '$HOME not set' unless defined $home; my $channelsList = "$home/.nix-channels"; my @channels; # Reads the list of channels from the file $channelsList; sub readChannels { return if (!-f $channelsList); open CHANNELS, "<$channelsList" or die "cannot open `$channelsList': $!"; while (<CHANNELS>) { chomp; push @channels, $_; } close CHANNELS; } # Writes the list of channels to the file $channelsList; sub writeChannels { open CHANNELS, ">$channelsList" or die "cannot open `$channelsList': $!"; foreach my $url (@channels) { print CHANNELS "$url\n"; } close CHANNELS; } # Adds a channel to the file $channelsList; sub addChannel { my $url = shift; readChannels; foreach my $url2 (@channels) { return if $url eq $url2; } push @channels, $url; writeChannels; } # Fetch Nix expressions and pull cache manifests from the subscribed # channels. sub update { readChannels; # Get rid of all the old substitutes. system "@bindir@/nix-store --clear-substitutes"; die "cannot clear substitutes" if ($? != 0); # Pull cache manifests. foreach my $url (@channels) { print "pulling cache manifest from `$url'\n"; system "@bindir@/nix-pull '$url'/MANIFEST"; die "cannot pull cache manifest from `$url'" if ($? != 0); } # Create a Nix expression that fetches and unpacks the channel Nix # expressions. my $nixExpr = "["; foreach my $url (@channels) { my $fullURL = "$url/nixexprs.tar.bz2"; my $hash = `@bindir@/nix-prefetch-url '$fullURL' 2> /dev/null` or die "cannot fetch `$fullURL'"; chomp $hash; # !!! escaping $nixExpr .= "((import @datadir@/nix/corepkgs/fetchurl) " . "{url = $fullURL; md5 = \"$hash\"; system = \"@system@\";}) " } $nixExpr .= "]"; $nixExpr = "(import @datadir@/nix/corepkgs/channels/unpack.nix) " . "{inputs = $nixExpr; system = \"@system@\";}"; # Instantiate the Nix expression. my $storeExpr = `echo '$nixExpr' | @bindir@/nix-instantiate -` or die "cannot instantiate Nix expression"; chomp $storeExpr; # Register the store expression as a root of the garbage # collector. my $userName = getpwuid($<); die "who ARE you? go away" unless defined $userName; my $rootFile = "$rootsDir/$userName.gcroot"; my $tmpRootFile = "$rootsDir/$userName-tmp.gcroot"; open ROOT, ">$tmpRootFile" or die "cannot create `$tmpRootFile': $!"; print ROOT "$storeExpr"; close ROOT; # Realise the store expression. my $outPath = `nix-store -qnf '$storeExpr'` or die "cannot realise store expression"; chomp $outPath; # Make it the default Nix expression for `nix-env'. system "@bindir@/nix-env --import '$outPath'"; die "cannot pull set default Nix expression to `$outPath'" if ($? != 0); rename $tmpRootFile, $rootFile or die "cannot rename `$tmpRootFile' to `$rootFile': $!"; } while (scalar @ARGV) { my $arg = shift @ARGV; if ($arg eq "--add") { die "syntax: nix-channel --add URL" if (scalar @ARGV != 1); addChannel (shift @ARGV); last; } elsif ($arg eq "--update") { die "syntax: nix-channel --update" if (scalar @ARGV != 0); update; last; } else { die "unknown argument `$arg'"; } }