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
 | 
					struct CmdRun : InstallablesCommand
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Strings command = { "bash" };
 | 
					    Strings command = { "bash" };
 | 
				
			||||||
 | 
					    StringSet keep, unset;
 | 
				
			||||||
 | 
					    bool ignoreEnvironment = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CmdRun()
 | 
					    CmdRun()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					@ -31,6 +33,28 @@ struct CmdRun : InstallablesCommand
 | 
				
			||||||
                if (ss.empty()) throw UsageError("--command requires at least one argument");
 | 
					                if (ss.empty()) throw UsageError("--command requires at least one argument");
 | 
				
			||||||
                command = ss;
 | 
					                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
 | 
					    std::string name() override
 | 
				
			||||||
| 
						 | 
					@ -49,6 +73,31 @@ struct CmdRun : InstallablesCommand
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto accessor = store->getFSAccessor();
 | 
					        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"), ":");
 | 
					        auto unixPath = tokenizeString<Strings>(getEnv("PATH"), ":");
 | 
				
			||||||
        for (auto & path : outPaths)
 | 
					        for (auto & path : outPaths)
 | 
				
			||||||
            if (accessor->stat(path + "/bin").type != FSAccessor::tMissing)
 | 
					            if (accessor->stat(path + "/bin").type != FSAccessor::tMissing)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue