nix run: Add some flags for clearing/keeping the environment
This is useful for testing commands in isolation. For example, $ nix run nixpkgs.geeqie -i -k DISPLAY -k XAUTHORITY -c geeqie runs geeqie in an empty environment, except for $DISPLAY and $XAUTHORITY.
This commit is contained in:
		
							parent
							
								
									5cc8609e30
								
							
						
					
					
						commit
						05d68a6e23
					
				
					 1 changed files with 49 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -18,6 +18,8 @@ std::string chrootHelperName = "__run_in_chroot";
 | 
			
		|||
struct CmdRun : InstallablesCommand
 | 
			
		||||
{
 | 
			
		||||
    Strings command = { "bash" };
 | 
			
		||||
    StringSet keep, unset;
 | 
			
		||||
    bool ignoreEnvironment = false;
 | 
			
		||||
 | 
			
		||||
    CmdRun()
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -31,6 +33,28 @@ struct CmdRun : InstallablesCommand
 | 
			
		|||
                if (ss.empty()) throw UsageError("--command requires at least one argument");
 | 
			
		||||
                command = ss;
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        mkFlag()
 | 
			
		||||
            .longName("ignore-environment")
 | 
			
		||||
            .shortName('i')
 | 
			
		||||
            .description("clear the entire environment (except those specified with --keep)")
 | 
			
		||||
            .handler([&](Strings ss) { ignoreEnvironment = true; });
 | 
			
		||||
 | 
			
		||||
        mkFlag()
 | 
			
		||||
            .longName("keep")
 | 
			
		||||
            .shortName('k')
 | 
			
		||||
            .description("keep specified environment variable")
 | 
			
		||||
            .arity(1)
 | 
			
		||||
            .labels({"name"})
 | 
			
		||||
            .handler([&](Strings ss) { keep.insert(ss.front()); });
 | 
			
		||||
 | 
			
		||||
        mkFlag()
 | 
			
		||||
            .longName("unset")
 | 
			
		||||
            .shortName('u')
 | 
			
		||||
            .description("unset specified environment variable")
 | 
			
		||||
            .arity(1)
 | 
			
		||||
            .labels({"name"})
 | 
			
		||||
            .handler([&](Strings ss) { unset.insert(ss.front()); });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string name() override
 | 
			
		||||
| 
						 | 
				
			
			@ -49,6 +73,31 @@ struct CmdRun : InstallablesCommand
 | 
			
		|||
 | 
			
		||||
        auto accessor = store->getFSAccessor();
 | 
			
		||||
 | 
			
		||||
        if (ignoreEnvironment) {
 | 
			
		||||
 | 
			
		||||
            if (!unset.empty())
 | 
			
		||||
                throw UsageError("--unset does not make sense with --ignore-environment");
 | 
			
		||||
 | 
			
		||||
            std::map<std::string, std::string> kept;
 | 
			
		||||
            for (auto & var : keep) {
 | 
			
		||||
                auto s = getenv(var.c_str());
 | 
			
		||||
                if (s) kept[var] = s;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            clearenv();
 | 
			
		||||
 | 
			
		||||
            for (auto & var : kept)
 | 
			
		||||
                setenv(var.first.c_str(), var.second.c_str(), 1);
 | 
			
		||||
 | 
			
		||||
        } else {
 | 
			
		||||
 | 
			
		||||
            if (!keep.empty())
 | 
			
		||||
                throw UsageError("--keep does not make sense without --ignore-environment");
 | 
			
		||||
 | 
			
		||||
            for (auto & var : unset)
 | 
			
		||||
                unsetenv(var.c_str());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        auto unixPath = tokenizeString<Strings>(getEnv("PATH"), ":");
 | 
			
		||||
        for (auto & path : outPaths)
 | 
			
		||||
            if (accessor->stat(path + "/bin").type != FSAccessor::tMissing)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue