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>
6 This file is part of GNU Guix.
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.
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.
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/>. */
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. */
28 #include <local-store.hh>
40 /* Input stream where we read closure descriptions. */
41 static std::istream
*input
= &std::cin
;
45 /* Command-line options. */
47 const char *argp_program_version
=
48 "guix-register (" PACKAGE_NAME
") " PACKAGE_VERSION
;
49 const char *argp_program_bug_address
= PACKAGE_BUGREPORT
;
52 "guix-register -- register a closure as valid in a store\
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 \
59 #define GUIX_OPT_STATE_DIRECTORY 1
60 #define GUIX_OPT_DEDUPLICATE 2
62 static const struct argp_option options
[] =
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" },
74 /* Prefix of the store being populated. */
75 static std::string prefix
;
77 /* Whether to deduplicate the registered store items. */
78 static bool deduplication
= true;
80 /* Parse a single option. */
82 parse_opt (int key
, char *arg
, struct argp_state
*state
)
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";
97 case GUIX_OPT_STATE_DIRECTORY
:
99 string state_dir
= canonPath (arg
);
101 settings
.nixStateDir
= state_dir
;
102 settings
.nixDBPath
= state_dir
+ "/db";
106 case GUIX_OPT_DEDUPLICATE
:
107 deduplication
= false;
114 if (state
->arg_num
>= 2)
115 /* Too many arguments. */
118 file
= new std::ifstream ();
126 return (error_t
) ARGP_ERR_UNKNOWN
;
132 /* Argument parsing. */
133 static struct argp argp
= { options
, parse_opt
, 0, doc
};
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:
146 This is really meant as an internal format. */
148 register_validity (LocalStore
*store
, std::istream
&input
,
149 bool optimize
= true,
150 bool reregister
= true, bool hashGiven
= false,
151 bool canonicalise
= true)
153 ValidPathInfos infos
;
157 ValidPathInfo info
= decodeValidPathInfo (input
, hashGiven
);
161 if (!prefix
.empty ())
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
);
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
);
173 if (!store
->isValidPath (info
.path
) || reregister
)
177 canonicalisePathMetaData (real_path
, -1);
181 HashResult hash
= hashPath (htSHA256
, real_path
);
182 info
.hash
= hash
.first
;
183 info
.narSize
= hash
.second
;
185 infos
.push_back (info
);
189 store
->registerValidPaths (infos
);
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. */
197 /* Make sure deduplication is enabled. */
198 settings
.autoOptimiseStore
= true;
200 std::string store_dir
= settings
.nixStore
;
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
;
215 main (int argc
, char *argv
[])
217 /* Initialize libgcrypt, which is indirectly used. */
218 if (!gcry_check_version (GCRYPT_VERSION
))
220 fprintf (stderr
, "error: libgcrypt version mismatch\n");
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);
228 /* Honor the environment variables, and initialize the settings. */
229 settings
.processEnvironment ();
233 argp_parse (&argp
, argc
, argv
, 0, 0, 0);
235 /* Instantiate the store. This creates any missing directories among
236 'settings.nixStore', 'settings.nixDBPath', etc. */
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
;
245 register_validity (&store
, *input
, deduplication
);
247 catch (std::exception
&e
)
249 fprintf (stderr
, "error: %s\n", e
.what ());