I.e. do what git does. I'm too lazy to keep the builtin help text up to date :-) Also add ‘--help’ to various commands that lacked it (e.g. nix-collect-garbage).
		
			
				
	
	
		
			207 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			Text
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			207 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			Text
		
	
	
		
			Executable file
		
	
	
	
	
| #! @perl@ -w @perlFlags@
 | |
| 
 | |
| use strict;
 | |
| use File::Basename;
 | |
| use File::Path qw(mkpath);
 | |
| use Nix::Config;
 | |
| use Nix::Manifest;
 | |
| 
 | |
| Nix::Config::readConfig;
 | |
| 
 | |
| my $manifestDir = $Nix::Config::manifestDir;
 | |
| 
 | |
| 
 | |
| # Turn on caching in nix-prefetch-url.
 | |
| my $channelCache = "$Nix::Config::stateDir/channel-cache";
 | |
| mkdir $channelCache, 0755 unless -e $channelCache;
 | |
| $ENV{'NIX_DOWNLOAD_CACHE'} = $channelCache if -W $channelCache;
 | |
| 
 | |
| # Figure out the name of the `.nix-channels' file to use.
 | |
| my $home = $ENV{"HOME"} or die '$HOME not set\n';
 | |
| my $channelsList = "$home/.nix-channels";
 | |
| my $nixDefExpr = "$home/.nix-defexpr";
 | |
| 
 | |
| # Figure out the name of the channels profile.
 | |
| my $userName = getpwuid($<) or die "cannot figure out user name";
 | |
| my $profile = "$Nix::Config::stateDir/profiles/per-user/$userName/channels";
 | |
| mkpath(dirname $profile, 0, 0755);
 | |
| 
 | |
| my %channels;
 | |
| 
 | |
| 
 | |
| # Reads the list of channels.
 | |
| sub readChannels {
 | |
|     return if (!-f $channelsList);
 | |
|     open CHANNELS, "<$channelsList" or die "cannot open `$channelsList': $!";
 | |
|     while (<CHANNELS>) {
 | |
|         chomp;
 | |
|         next if /^\s*\#/;
 | |
|         my ($url, $name) = split ' ', $_;
 | |
|         $url =~ s/\/*$//; # remove trailing slashes
 | |
|         $name = basename $url unless defined $name;
 | |
|         $channels{$name} = $url;
 | |
|     }
 | |
|     close CHANNELS;
 | |
| }
 | |
| 
 | |
| 
 | |
| # Writes the list of channels.
 | |
| sub writeChannels {
 | |
|     open CHANNELS, ">$channelsList" or die "cannot open `$channelsList': $!";
 | |
|     foreach my $name (keys %channels) {
 | |
|         print CHANNELS "$channels{$name} $name\n";
 | |
|     }
 | |
|     close CHANNELS;
 | |
| }
 | |
| 
 | |
| 
 | |
| # Adds a channel.
 | |
| sub addChannel {
 | |
|     my ($url, $name) = @_;
 | |
|     readChannels;
 | |
|     $channels{$name} = $url;
 | |
|     writeChannels;
 | |
| }
 | |
| 
 | |
| 
 | |
| # Remove a channel.
 | |
| sub removeChannel {
 | |
|     my ($name) = @_;
 | |
|     readChannels;
 | |
|     my $url = $channels{$name};
 | |
|     deleteOldManifests($url . "/MANIFEST", undef) if defined $url;
 | |
|     delete $channels{$name};
 | |
|     writeChannels;
 | |
| 
 | |
|     system("$Nix::Config::binDir/nix-env --profile '$profile' -e '$name'") == 0
 | |
|         or die "cannot remove channel `$name'\n";
 | |
| }
 | |
| 
 | |
| 
 | |
| # Fetch Nix expressions and pull manifests from the subscribed
 | |
| # channels.
 | |
| sub update {
 | |
|     my @channelNames = @_;
 | |
| 
 | |
|     readChannels;
 | |
| 
 | |
|     # Download each channel.
 | |
|     my $exprs = "";
 | |
|     foreach my $name (keys %channels) {
 | |
|         next if scalar @channelNames > 0 && ! grep { $_ eq $name } @{channelNames};
 | |
| 
 | |
|         my $url = $channels{$name};
 | |
|         my $origUrl = "$url/MANIFEST";
 | |
| 
 | |
|         # Check if $url is a redirect.  If so, follow it now to ensure
 | |
|         # consistency if the redirection is changed between
 | |
|         # downloading the manifest and the tarball.
 | |
|         my $headers = `$Nix::Config::curl --silent --head '$url'`;
 | |
|         die "$0: unable to check `$url'\n" if $? != 0;
 | |
|         $headers =~ s/\r//g;
 | |
|         $url = $1 if $headers =~ /^Location:\s*(.*)\s*$/m;
 | |
| 
 | |
|         # Check if the channel advertises a binary cache.
 | |
|         my $binaryCacheURL = `$Nix::Config::curl --silent '$url'/binary-cache-url`;
 | |
|         my $extraAttrs = "";
 | |
|         my $getManifest = ($Nix::Config::config{"force-manifest"} // "false") eq "true";
 | |
|         if ($? == 0 && $binaryCacheURL ne "") {
 | |
|             $extraAttrs .= "binaryCacheURL = \"$binaryCacheURL\"; ";
 | |
|             deleteOldManifests($origUrl, undef);
 | |
|         } else {
 | |
|             $getManifest = 1;
 | |
|         }
 | |
| 
 | |
|         if ($getManifest) {
 | |
|             # No binary cache, so pull the channel manifest.
 | |
|             mkdir $manifestDir, 0755 unless -e $manifestDir;
 | |
|             die "$0: you do not have write permission to `$manifestDir'!\n" unless -W $manifestDir;
 | |
|             $ENV{'NIX_ORIG_URL'} = $origUrl;
 | |
|             system("$Nix::Config::binDir/nix-pull", "--skip-wrong-store", "$url/MANIFEST") == 0
 | |
|                 or die "cannot pull manifest from `$url'\n";
 | |
|         }
 | |
| 
 | |
|         # Download the channel tarball.
 | |
|         my $fullURL = "$url/nixexprs.tar.bz2";
 | |
|         print STDERR "downloading Nix expressions from `$fullURL'...\n";
 | |
|         my ($hash, $path) = `PRINT_PATH=1 QUIET=1 $Nix::Config::binDir/nix-prefetch-url '$fullURL'`;
 | |
|         die "cannot fetch `$fullURL'\n" if $? != 0;
 | |
|         chomp $path;
 | |
| 
 | |
|         # If the URL contains a version number, append it to the name
 | |
|         # attribute (so that "nix-env -q" on the channels profile
 | |
|         # shows something useful).
 | |
|         my $cname = $name;
 | |
|         $cname .= $1 if basename($url) =~ /(-\d.*)$/;
 | |
| 
 | |
|         $exprs .= "'f: f { name = \"$cname\"; channelName = \"$name\"; src = builtins.storePath \"$path\"; $extraAttrs }' ";
 | |
|     }
 | |
| 
 | |
|     # Unpack the channel tarballs into the Nix store and install them
 | |
|     # into the channels profile.
 | |
|     print STDERR "unpacking channels...\n";
 | |
|     system("$Nix::Config::binDir/nix-env --profile '$profile' " .
 | |
|            "-f '<nix/unpack-channel.nix>' -i -E $exprs --quiet") == 0
 | |
|            or die "cannot unpack the channels";
 | |
| 
 | |
|     # Make the channels appear in nix-env.
 | |
|     unlink $nixDefExpr if -l $nixDefExpr; # old-skool ~/.nix-defexpr
 | |
|     mkdir $nixDefExpr or die "cannot create directory `$nixDefExpr'" if !-e $nixDefExpr;
 | |
|     my $channelLink = "$nixDefExpr/channels";
 | |
|     unlink $channelLink; # !!! not atomic
 | |
|     symlink($profile, $channelLink) or die "cannot symlink `$channelLink' to `$profile'";
 | |
| }
 | |
| 
 | |
| 
 | |
| die "$0: argument expected\n" if scalar @ARGV == 0;
 | |
| 
 | |
| 
 | |
| while (scalar @ARGV) {
 | |
|     my $arg = shift @ARGV;
 | |
| 
 | |
|     if ($arg eq "--add") {
 | |
|         die "$0: `--add' requires one or two arguments\n" if scalar @ARGV < 1 || scalar @ARGV > 2;
 | |
|         my $url = shift @ARGV;
 | |
|         my $name = shift @ARGV;
 | |
|         unless (defined $name) {
 | |
|             $name = basename $url;
 | |
|             $name =~ s/-unstable//;
 | |
|             $name =~ s/-stable//;
 | |
|         }
 | |
|         addChannel($url, $name);
 | |
|         last;
 | |
|     }
 | |
| 
 | |
|     if ($arg eq "--remove") {
 | |
|         die "$0: `--remove' requires one argument\n" if scalar @ARGV != 1;
 | |
|         removeChannel(shift @ARGV);
 | |
|         last;
 | |
|     }
 | |
| 
 | |
|     if ($arg eq "--list") {
 | |
|         die "$0: `--list' requires one argument\n" if scalar @ARGV != 0;
 | |
|         readChannels;
 | |
|         foreach my $name (keys %channels) {
 | |
|             print "$name $channels{$name}\n";
 | |
|         }
 | |
|         last;
 | |
|     }
 | |
| 
 | |
|     elsif ($arg eq "--update") {
 | |
|         update(@ARGV);
 | |
|         last;
 | |
|     }
 | |
| 
 | |
|     elsif ($arg eq "--help") {
 | |
|         exec "man nix-channel" or die;
 | |
|     }
 | |
| 
 | |
|     elsif ($arg eq "--version") {
 | |
|         print "nix-channel (Nix) $Nix::Config::version\n";
 | |
|         exit 0;
 | |
|     }
 | |
| 
 | |
|     else {
 | |
|         die "unknown argument `$arg'; try `--help'\n";
 | |
|     }
 | |
| }
 |