LTP GCOV extension - code coverage report
Current view: directory - src/nix-store - main.cc
Test: app.info
Date: 2004-12-21 Instrumented lines: 200
Code covered: 55.5 % Executed lines: 111

       1                 : #include <iostream>
       2                 : 
       3                 : #include "globals.hh"
       4                 : #include "normalise.hh"
       5                 : #include "gc.hh"
       6                 : #include "archive.hh"
       7                 : #include "shared.hh"
       8                 : #include "dotgraph.hh"
       9                 : #include "help.txt.hh"
      10                 : 
      11                 : 
      12                 : typedef void (* Operation) (Strings opFlags, Strings opArgs);
      13                 : 
      14                 : 
      15                 : void printHelp()
      16               0 : {
      17               0 :     cout << string((char *) helpText, sizeof helpText);
      18                 : }
      19                 : 
      20                 : 
      21                 : /* Realise paths from the given store expressions. */
      22                 : static void opRealise(Strings opFlags, Strings opArgs)
      23               7 : {
      24           19063 :     if (!opFlags.empty()) throw UsageError("unknown flag");
      25                 : 
      26              14 :     for (Strings::iterator i = opArgs.begin();
      27                 :          i != opArgs.end(); i++)
      28                 :     {
      29               7 :         Path nfPath = realiseStoreExpr(*i);
      30               7 :         cout << format("%1%\n") % (string) nfPath;
      31                 :     }
      32                 : }
      33                 : 
      34                 : 
      35                 : /* Add paths to the Nix values directory and print the hashes of those
      36                 :    paths. */
      37                 : static void opAdd(Strings opFlags, Strings opArgs)
      38               0 : {
      39               0 :     if (!opFlags.empty()) throw UsageError("unknown flag");
      40                 : 
      41               0 :     for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); i++)
      42               0 :         cout << format("%1%\n") % addToStore(*i);
      43                 : }
      44                 : 
      45                 : 
      46                 : Path maybeNormalise(const Path & ne, bool normalise, bool realise)
      47               9 : {
      48               9 :     if (realise) {
      49               6 :         Path ne2 = realiseStoreExpr(ne);
      50               6 :         return normalise ? ne2 : ne;
      51                 :     } else
      52               3 :         return normalise ? normaliseStoreExpr(ne) : ne;
      53                 : }
      54                 : 
      55                 : 
      56                 : /* Perform various sorts of queries. */
      57                 : static void opQuery(Strings opFlags, Strings opArgs)
      58               9 : {
      59                 :     enum { qList, qRequisites, qPredecessors, qGraph 
      60               9 :     } query = qList;
      61               9 :     bool normalise = false;
      62               9 :     bool realise = false;
      63               9 :     bool includeExprs = true;
      64               9 :     bool includeSuccessors = false;
      65                 : 
      66              23 :     for (Strings::iterator i = opFlags.begin();
      67                 :          i != opFlags.end(); i++)
      68              14 :         if (*i == "--list" || *i == "-l") query = qList;
      69              14 :         else if (*i == "--requisites" || *i == "-R") query = qRequisites;
      70              13 :         else if (*i == "--predecessors") query = qPredecessors;
      71              13 :         else if (*i == "--graph") query = qGraph;
      72              13 :         else if (*i == "--normalise" || *i == "-n") normalise = true;
      73               6 :         else if (*i == "--force-realise" || *i == "-f") realise = true;
      74               0 :         else if (*i == "--exclude-exprs") includeExprs = false;
      75               0 :         else if (*i == "--include-successors") includeSuccessors = true;
      76               0 :         else throw UsageError(format("unknown flag `%1%'") % *i);
      77                 : 
      78               9 :     switch (query) {
      79                 :         
      80                 :         case qList: {
      81              16 :             for (Strings::iterator i = opArgs.begin();
      82                 :                  i != opArgs.end(); i++)
      83                 :             {
      84                 :                 StringSet paths = storeExprRoots(
      85            4902 :                     maybeNormalise(*i, normalise, realise));
      86              16 :                 for (StringSet::iterator j = paths.begin(); 
      87                 :                      j != paths.end(); j++)
      88               8 :                     cout << format("%s\n") % *j;
      89                 :             }
      90               1 :             break;
      91                 :         }
      92                 : 
      93                 :         case qRequisites: {
      94               1 :             StringSet paths;
      95               2 :             for (Strings::iterator i = opArgs.begin();
      96                 :                  i != opArgs.end(); i++)
      97                 :             {
      98                 :                 StringSet paths2 = storeExprRequisites(
      99                 :                     maybeNormalise(*i, normalise, realise),
     100               1 :                     includeExprs, includeSuccessors);
     101               1 :                 paths.insert(paths2.begin(), paths2.end());
     102                 :             }
     103               4 :             for (StringSet::iterator i = paths.begin(); 
     104                 :                  i != paths.end(); i++)
     105               3 :                 cout << format("%s\n") % *i;
     106               1 :             break;
     107                 :         }
     108                 : 
     109                 :         case qPredecessors: {
     110               0 :             for (Strings::iterator i = opArgs.begin();
     111                 :                  i != opArgs.end(); i++)
     112                 :             {
     113            2564 :                 Paths preds = queryPredecessors(*i);
     114               0 :                 for (Paths::iterator j = preds.begin();
     115                 :                      j != preds.end(); j++)
     116               0 :                     cout << format("%s\n") % *j;
     117                 :             }
     118               0 :             break;
     119                 :         }
     120                 : 
     121                 :         case qGraph: {
     122               0 :             PathSet roots;
     123               0 :             for (Strings::iterator i = opArgs.begin();
     124                 :                  i != opArgs.end(); i++)
     125               0 :                 roots.insert(maybeNormalise(*i, normalise, realise));
     126               0 :             printDotGraph(roots);
     127               0 :             break;
     128                 :         }
     129                 : 
     130                 :         default:
     131               0 :             abort();
     132                 :     }
     133                 : }
     134                 : 
     135                 : 
     136                 : static void opSuccessor(Strings opFlags, Strings opArgs)
     137               3 : {
     138               3 :     if (!opFlags.empty()) throw UsageError("unknown flag");
     139               3 :     if (opArgs.size() % 2) throw UsageError("expecting even number of arguments");
     140                 : 
     141               3 :     Transaction txn;
     142               3 :     createStoreTransaction(txn);
     143               6 :     for (Strings::iterator i = opArgs.begin();
     144                 :          i != opArgs.end(); )
     145                 :     {
     146               3 :         Path path1 = *i++;
     147               3 :         Path path2 = *i++;
     148               3 :         registerSuccessor(txn, path1, path2);
     149                 :     }
     150               3 :     txn.commit();
     151                 : }
     152                 : 
     153                 : 
     154                 : static void opSubstitute(Strings opFlags, Strings opArgs)
     155               7 : {
     156               7 :     if (!opFlags.empty()) throw UsageError("unknown flag");
     157               7 :     if (!opArgs.empty())
     158               0 :         throw UsageError("no arguments expected");
     159                 : 
     160              21 :     SubstitutePairs subPairs;
     161               7 :     Transaction txn;
     162               7 :     createStoreTransaction(txn);
     163                 : 
     164              14 :     while (1) {
     165              14 :         Path srcPath;
     166            1030 :         Substitute sub;
     167              14 :         getline(cin, srcPath);
     168              14 :         if (cin.eof()) break;
     169               7 :         getline(cin, sub.storeExpr);
     170               7 :         getline(cin, sub.program);
     171               7 :         string s;
     172               7 :         getline(cin, s);
     173               7 :         int n;
     174               7 :         if (!string2Int(s, n)) throw Error("number expected");
     175              25 :         while (n--) {
     176              18 :             getline(cin, s);
     177              18 :             sub.args.push_back(s);
     178                 :         }
     179               7 :         if (!cin || cin.eof()) throw Error("missing input");
     180             149 :         subPairs.push_back(pair<Path, Substitute>(srcPath, sub));
     181                 :     }
     182                 : 
     183               7 :     registerSubstitutes(txn, subPairs);
     184                 :     
     185               7 :     txn.commit();
     186                 : }
     187                 : 
     188                 : 
     189                 : static void opValidPath(Strings opFlags, Strings opArgs)
     190               0 : {
     191               0 :     if (!opFlags.empty()) throw UsageError("unknown flag");
     192                 :     
     193               0 :     Transaction txn;
     194               0 :     createStoreTransaction(txn);
     195               0 :     for (Strings::iterator i = opArgs.begin();
     196                 :          i != opArgs.end(); ++i)
     197               0 :         registerValidPath(txn, *i);
     198               0 :     txn.commit();
     199                 : }
     200                 : 
     201                 : 
     202                 : static void opIsValid(Strings opFlags, Strings opArgs)
     203               0 : {
     204               0 :     if (!opFlags.empty()) throw UsageError("unknown flag");
     205                 : 
     206               0 :     for (Strings::iterator i = opArgs.begin();
     207                 :          i != opArgs.end(); ++i)
     208               0 :         if (!isValidPath(*i))
     209               0 :             throw Error(format("path `%1%' is not valid") % *i);
     210                 : }
     211                 : 
     212                 : 
     213                 : static void opGC(Strings opFlags, Strings opArgs)
     214               0 : {
     215                 :     /* Do what? */
     216               0 :     enum { soPrintLive, soPrintDead, soDelete } subOp;
     217               0 :     time_t minAge = 0;
     218               0 :     for (Strings::iterator i = opFlags.begin();
     219                 :          i != opFlags.end(); ++i)
     220               0 :         if (*i == "--print-live") subOp = soPrintLive;
     221               0 :         else if (*i == "--print-dead") subOp = soPrintDead;
     222               0 :         else if (*i == "--delete") subOp = soDelete;
     223               0 :         else if (*i == "--min-age") {
     224               0 :             int n;
     225               0 :             if (opArgs.size() == 0 || !string2Int(opArgs.front(), n))
     226               0 :                 throw UsageError("`--min-age' requires an integer argument");
     227               0 :             minAge = n;
     228                 :         }
     229               0 :         else throw UsageError(format("bad sub-operation `%1%' in GC") % *i);
     230                 :         
     231               0 :     Paths roots;
     232               0 :     while (1) {
     233               0 :         Path root;
     234               0 :         getline(cin, root);
     235               0 :         if (cin.eof()) break;
     236               0 :         roots.push_back(root);
     237                 :     }
     238                 : 
     239               0 :     PathSet live = findLivePaths(roots);
     240                 : 
     241               0 :     if (subOp == soPrintLive) {
     242               0 :         for (PathSet::iterator i = live.begin(); i != live.end(); ++i)
     243               0 :             cout << *i << endl;
     244               0 :         return;
     245                 :     }
     246                 : 
     247               0 :     PathSet dead = findDeadPaths(live, minAge * 3600);
     248                 : 
     249               0 :     if (subOp == soPrintDead) {
     250               0 :         for (PathSet::iterator i = dead.begin(); i != dead.end(); ++i)
     251               0 :             cout << *i << endl;
     252               0 :         return;
     253                 :     }
     254                 : 
     255               0 :     if (subOp == soDelete) {
     256                 : 
     257                 :         /* !!! What happens if the garbage collector run is aborted
     258                 :            halfway through?  In particular, dead paths can always
     259                 :            become live again (through re-instantiation), and might
     260                 :            then refer to deleted paths. => check instantiation
     261                 :            invariants */
     262                 : 
     263               0 :         for (PathSet::iterator i = dead.begin(); i != dead.end(); ++i) {
     264               0 :             printMsg(lvlInfo, format("deleting `%1%'") % *i);
     265               0 :             deleteFromStore(*i);
     266                 :         }
     267                 :     }
     268                 : }
     269                 : 
     270                 : 
     271                 : /* A sink that writes dump output to stdout. */
     272                 : struct StdoutSink : DumpSink
     273                 : {
     274                 :     virtual void operator ()
     275                 :         (const unsigned char * data, unsigned int len)
     276               0 :     {
     277               0 :         writeFull(STDOUT_FILENO, data, len);
     278                 :     }
     279                 : };
     280                 : 
     281                 : 
     282                 : /* Dump a path as a Nix archive.  The archive is written to standard
     283                 :    output. */
     284                 : static void opDump(Strings opFlags, Strings opArgs)
     285               0 : {
     286               0 :     if (!opFlags.empty()) throw UsageError("unknown flag");
     287               0 :     if (opArgs.size() != 1) throw UsageError("only one argument allowed");
     288                 : 
     289               0 :     StdoutSink sink;
     290               0 :     string path = *opArgs.begin();
     291               0 :     dumpPath(path, sink);
     292                 : }
     293                 : 
     294                 : 
     295                 : /* A source that read restore intput to stdin. */
     296                 : struct StdinSource : RestoreSource
     297                 : {
     298                 :     virtual void operator () (unsigned char * data, unsigned int len)
     299               0 :     {
     300               0 :         readFull(STDIN_FILENO, data, len);
     301                 :     }
     302                 : };
     303                 : 
     304                 : 
     305                 : /* Restore a value from a Nix archive.  The archive is written to
     306                 :    standard input. */
     307                 : static void opRestore(Strings opFlags, Strings opArgs)
     308               0 : {
     309               0 :     if (!opFlags.empty()) throw UsageError("unknown flag");
     310               0 :     if (opArgs.size() != 1) throw UsageError("only one argument allowed");
     311                 : 
     312               0 :     StdinSource source;
     313               0 :     restorePath(*opArgs.begin(), source);
     314                 : }
     315                 : 
     316                 : 
     317                 : /* Initialise the Nix databases. */
     318                 : static void opInit(Strings opFlags, Strings opArgs)
     319               1 : {
     320               1 :     if (!opFlags.empty()) throw UsageError("unknown flag");
     321               1 :     if (!opArgs.empty())
     322               0 :         throw UsageError("no arguments expected");
     323               1 :     initDB();
     324                 : }
     325                 : 
     326                 : 
     327                 : /* Verify the consistency of the Nix environment. */
     328                 : static void opVerify(Strings opFlags, Strings opArgs)
     329               1 : {
     330               1 :     verifyStore();
     331                 : }
     332                 : 
     333                 : 
     334                 : /* Scan the arguments; find the operation, set global flags, put all
     335                 :    other flags in a list, and put all other arguments in another
     336                 :    list. */
     337                 : void run(Strings args)
     338              28 : {
     339              28 :     Strings opFlags, opArgs;
     340              28 :     Operation op = 0;
     341                 : 
     342              92 :     for (Strings::iterator i = args.begin(); i != args.end(); ++i) {
     343              64 :         string arg = *i;
     344                 : 
     345              64 :         Operation oldOp = op;
     346                 : 
     347              64 :         if (arg == "--realise" || arg == "-r")
     348               7 :             op = opRealise;
     349              57 :         else if (arg == "--add" || arg == "-A")
     350               0 :             op = opAdd;
     351              57 :         else if (arg == "--query" || arg == "-q")
     352               9 :             op = opQuery;
     353              48 :         else if (arg == "--successor")
     354               3 :             op = opSuccessor;
     355              45 :         else if (arg == "--substitute")
     356               7 :             op = opSubstitute;
     357              38 :         else if (arg == "--validpath")
     358               0 :             op = opValidPath;
     359              38 :         else if (arg == "--isvalid")
     360               0 :             op = opIsValid;
     361              38 :         else if (arg == "--gc")
     362               0 :             op = opGC;
     363              38 :         else if (arg == "--dump")
     364               0 :             op = opDump;
     365              38 :         else if (arg == "--restore")
     366               0 :             op = opRestore;
     367              38 :         else if (arg == "--init")
     368               1 :             op = opInit;
     369              37 :         else if (arg == "--verify")
     370               1 :             op = opVerify;
     371              36 :         else if (arg[0] == '-')
     372              14 :             opFlags.push_back(arg);
     373                 :         else
     374              22 :             opArgs.push_back(arg);
     375                 : 
     376              64 :         if (oldOp && oldOp != op)
     377               0 :             throw UsageError("only one operation may be specified");
     378                 :     }
     379                 : 
     380              28 :     if (!op) throw UsageError("no operation specified");
     381                 : 
     382              28 :     if (op != opDump && op != opRestore) /* !!! hack */
     383              28 :         openDB();
     384                 : 
     385              28 :     op(opFlags, opArgs);
     386                 : }
     387                 : 
     388                 : 
     389              56 : string programId = "nix-store";

Generated by: LTP GCOV extension version 1.1