You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

255 lines
6.9 KiB

  1. /* GNU Guix --- Functional package management for GNU
  2. Copyright (C) 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
  3. Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012,
  4. 2013 Eelco Dolstra <eelco.dolstra@logicblox.com>
  5. This file is part of GNU Guix.
  6. GNU Guix is free software; you can redistribute it and/or modify it
  7. under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 3 of the License, or (at
  9. your option) any later version.
  10. GNU Guix is distributed in the hope that it will be useful, but
  11. WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. */
  16. /* This file derives from the implementation of 'nix-store
  17. --register-validity', by Eelco Dolstra, as found in the Nix package
  18. manager's src/nix-store/nix-store.cc. */
  19. #include <config.h>
  20. #include <globals.hh>
  21. #include <local-store.hh>
  22. #include <iostream>
  23. #include <fstream>
  24. #include <cstdlib>
  25. #include <cstdio>
  26. #include <argp.h>
  27. #include <gcrypt.h>
  28. using namespace nix;
  29. /* Input stream where we read closure descriptions. */
  30. static std::istream *input = &std::cin;
  31. /* Command-line options. */
  32. const char *argp_program_version =
  33. "guix-register (" PACKAGE_NAME ") " PACKAGE_VERSION;
  34. const char *argp_program_bug_address = PACKAGE_BUGREPORT;
  35. static char doc[] =
  36. "guix-register -- register a closure as valid in a store\
  37. \v\
  38. This program is used internally when populating a store with data \
  39. from an existing store. It updates the new store's database with \
  40. information about which store files are valid, and what their \
  41. references are.";
  42. #define GUIX_OPT_STATE_DIRECTORY 1
  43. #define GUIX_OPT_DEDUPLICATE 2
  44. static const struct argp_option options[] =
  45. {
  46. { "prefix", 'p', "DIRECTORY", 0,
  47. "Open the store that lies under DIRECTORY" },
  48. { "state-directory", GUIX_OPT_STATE_DIRECTORY, "DIRECTORY", 0,
  49. "Use DIRECTORY as the state directory of the target store" },
  50. { "no-deduplication", GUIX_OPT_DEDUPLICATE, 0, 0,
  51. "Disable automatic deduplication of registered store items" },
  52. { 0, 0, 0, 0, 0 }
  53. };
  54. /* Prefix of the store being populated. */
  55. static std::string prefix;
  56. /* Whether to deduplicate the registered store items. */
  57. static bool deduplication = true;
  58. /* Parse a single option. */
  59. static error_t
  60. parse_opt (int key, char *arg, struct argp_state *state)
  61. {
  62. switch (key)
  63. {
  64. case 'p':
  65. {
  66. prefix = canonPath (arg);
  67. settings.nixStore = prefix + NIX_STORE_DIR;
  68. settings.nixDataDir = prefix + NIX_DATA_DIR;
  69. settings.nixLogDir = prefix + NIX_LOG_DIR;
  70. settings.nixStateDir = prefix + NIX_STATE_DIR;
  71. settings.nixDBPath = settings.nixStateDir + "/db";
  72. break;
  73. }
  74. case GUIX_OPT_STATE_DIRECTORY:
  75. {
  76. string state_dir = canonPath (arg);
  77. settings.nixStateDir = state_dir;
  78. settings.nixDBPath = state_dir + "/db";
  79. break;
  80. }
  81. case GUIX_OPT_DEDUPLICATE:
  82. deduplication = false;
  83. break;
  84. case ARGP_KEY_ARG:
  85. {
  86. std::ifstream *file;
  87. if (state->arg_num >= 2)
  88. /* Too many arguments. */
  89. argp_usage (state);
  90. file = new std::ifstream ();
  91. file->open (arg);
  92. input = file;
  93. }
  94. break;
  95. default:
  96. return (error_t) ARGP_ERR_UNKNOWN;
  97. }
  98. return (error_t) 0;
  99. }
  100. /* Argument parsing. */
  101. static struct argp argp = { options, parse_opt, 0, doc };
  102. /* Read from INPUT the description of a closure, and register it as valid in
  103. STORE. The expected format on INPUT is that used by #:references-graphs:
  104. FILE
  105. DERIVER
  106. NUMBER-OF-REFERENCES
  107. REF1
  108. ...
  109. REFN
  110. This is really meant as an internal format. */
  111. static void
  112. register_validity (LocalStore *store, std::istream &input,
  113. bool optimize = true,
  114. bool reregister = true, bool hashGiven = false,
  115. bool canonicalise = true)
  116. {
  117. ValidPathInfos infos;
  118. while (1)
  119. {
  120. ValidPathInfo info = decodeValidPathInfo (input, hashGiven);
  121. if (info.path == "")
  122. break;
  123. if (!prefix.empty ())
  124. {
  125. /* Rewrite the input to refer to the final name, as if we were in a
  126. chroot under PREFIX. */
  127. std::string final_prefix (NIX_STORE_DIR "/");
  128. info.path = final_prefix + baseNameOf (info.path);
  129. }
  130. /* Keep its real path to canonicalize it and compute its hash. */
  131. std::string real_path;
  132. real_path = prefix + "/" + settings.nixStore + "/" + baseNameOf (info.path);
  133. if (!store->isValidPath (info.path) || reregister)
  134. {
  135. /* !!! races */
  136. if (canonicalise)
  137. canonicalisePathMetaData (real_path, -1);
  138. if (!hashGiven)
  139. {
  140. HashResult hash = hashPath (htSHA256, real_path);
  141. info.hash = hash.first;
  142. info.narSize = hash.second;
  143. }
  144. infos.push_back (info);
  145. }
  146. }
  147. store->registerValidPaths (infos);
  148. /* XXX: When PREFIX is non-empty, store->linksDir points to the original
  149. store's '.links' directory, which means 'optimisePath' would try to link
  150. to that instead of linking to the target store. Thus, disable
  151. deduplication in this case. */
  152. if (optimize)
  153. {
  154. /* Make sure deduplication is enabled. */
  155. settings.autoOptimiseStore = true;
  156. std::string store_dir = settings.nixStore;
  157. /* 'optimisePath' creates temporary links under 'settings.nixStore' and
  158. this must be the real target store, under PREFIX, to avoid
  159. cross-device links. Thus, temporarily switch the value of
  160. 'settings.nixStore'. */
  161. settings.nixStore = prefix + store_dir;
  162. for (auto&& i: infos)
  163. store->optimisePath (prefix + i.path);
  164. settings.nixStore = store_dir;
  165. }
  166. }
  167. int
  168. main (int argc, char *argv[])
  169. {
  170. /* Initialize libgcrypt, which is indirectly used. */
  171. if (!gcry_check_version (GCRYPT_VERSION))
  172. {
  173. fprintf (stderr, "error: libgcrypt version mismatch\n");
  174. exit (EXIT_FAILURE);
  175. }
  176. /* Tell Libgcrypt that initialization has completed, as per the Libgcrypt
  177. 1.6.0 manual (although this does not appear to be strictly needed.) */
  178. gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
  179. /* Honor the environment variables, and initialize the settings. */
  180. settings.processEnvironment ();
  181. try
  182. {
  183. argp_parse (&argp, argc, argv, 0, 0, 0);
  184. /* Instantiate the store. This creates any missing directories among
  185. 'settings.nixStore', 'settings.nixDBPath', etc. */
  186. LocalStore store;
  187. if (!prefix.empty ())
  188. /* Under the --prefix tree, the final name of the store will be
  189. NIX_STORE_DIR. Set it here so that the database uses file names
  190. prefixed by NIX_STORE_DIR and not PREFIX + NIX_STORE_DIR. */
  191. settings.nixStore = NIX_STORE_DIR;
  192. register_validity (&store, *input, deduplication);
  193. }
  194. catch (std::exception &e)
  195. {
  196. fprintf (stderr, "error: %s\n", e.what ());
  197. return EXIT_FAILURE;
  198. }
  199. return EXIT_SUCCESS;
  200. }