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