@@ -77,11 +77,16 @@ namespace {
7777 return NO_COMPRESS;
7878}
7979
80+ #define VPKEDIT_ERROR_TYPE (name ) class vpkedit_ ##name##_error : public std::runtime_error { public: using runtime_error::runtime_error; }
81+ VPKEDIT_ERROR_TYPE (load);
82+ VPKEDIT_ERROR_TYPE (invalid_argument);
83+ VPKEDIT_ERROR_TYPE (runtime);
84+
8085// / Extract file(s) from an existing pack file
8186void extract (const argparse::ArgumentParser& cli, const std::string& inputPath) {
8287 auto packFile = PackFile::open (inputPath);
8388 if (!packFile) {
84- std::cerr << " Could not open the pack file at \" " << inputPath << " \" : it failed to load!" << std::endl ;
89+ throw vpkedit_load_error{ " Could not open the pack file at \" " + inputPath + " \" : it failed to load!" } ;
8590 }
8691
8792 auto extractPath = cli.get (ARG_S (EXTRACT));
@@ -92,14 +97,13 @@ void extract(const argparse::ArgumentParser& cli, const std::string& inputPath)
9297 outputPath = cli.get (ARG_S (OUTPUT));
9398 }
9499 if (!std::filesystem::exists (outputPath) || !std::filesystem::is_directory (outputPath)) {
95- std::cerr << " Output location must be an existing directory!" << std::endl;
96- return ;
100+ throw vpkedit_invalid_argument_error{" Output location must be an existing directory!" };
97101 }
98102 if (!packFile->extractAll (outputPath)) {
99- std::cerr
100- << " Could not extract pack file contents to \" " << outputPath << " \" !\n "
101- << " Please ensure that a game or another application is not using the file, and that you have sufficient permissions to write to the output location."
102- << std::endl ;
103+ throw vpkedit_runtime_error{
104+ " Could not extract pack file contents to \" " + outputPath + " \" !\n "
105+ " Please ensure that a game or another application is not using the file, and that you have sufficient permissions to write to the output location."
106+ } ;
103107 }
104108 std::cout << " Extracted pack file contents under \" " << outputPath << " \" ." << std::endl;
105109 } else if (extractPath.ends_with (' /' )) {
@@ -109,14 +113,13 @@ void extract(const argparse::ArgumentParser& cli, const std::string& inputPath)
109113 outputPath = cli.get (ARG_S (OUTPUT));
110114 }
111115 if (!std::filesystem::exists (outputPath) || !std::filesystem::is_directory (outputPath)) {
112- std::cerr << " Output location must be an existing directory!" << std::endl;
113- return ;
116+ throw vpkedit_invalid_argument_error{" Output location must be an existing directory!" };
114117 }
115118 if (!packFile->extractDirectory (extractPath, outputPath)) {
116- std::cerr
117- << " Some or all files were unable to be extracted to \" " << outputPath << " \" !\n "
118- << " Please ensure that a game or another application is not using the file, and that you have sufficient permissions to write to the output location."
119- << std::endl ;
119+ throw vpkedit_runtime_error{
120+ " Some or all files were unable to be extracted to \" " + outputPath + " \" !\n "
121+ " Please ensure that a game or another application is not using the file, and that you have sufficient permissions to write to the output location."
122+ } ;
120123 }
121124 std::cout << " Extracted directory under \" " << outputPath << " \" ." << std::endl;
122125 } else {
@@ -127,14 +130,13 @@ void extract(const argparse::ArgumentParser& cli, const std::string& inputPath)
127130 }
128131 auto entry = packFile->findEntry (extractPath);
129132 if (!entry) {
130- std::cerr << " Could not find file at \" " << extractPath << " \" in the pack file!" << std::endl;
131- return ;
133+ throw vpkedit_runtime_error{" Could not find file at \" " + extractPath + " \" in the pack file!" };
132134 }
133135 if (!packFile->extractEntry (extractPath, outputPath)) {
134- std::cerr
135- << " Could not extract file at \" " << extractPath << " \" to \" " << outputPath << " \" !\n "
136- << " Please ensure that a game or another application is not using the file, and that you have sufficient permissions to write to the output location."
137- << std::endl ;
136+ throw vpkedit_runtime_error{
137+ " Could not extract file at \" " + extractPath + " \" to \" " + outputPath + " \" !\n "
138+ " Please ensure that a game or another application is not using the file, and that you have sufficient permissions to write to the output location."
139+ } ;
138140 }
139141 std::cout << " Extracted file at \" " << extractPath << " \" to \" " << outputPath << " \" ." << std::endl;
140142 }
@@ -144,16 +146,15 @@ void extract(const argparse::ArgumentParser& cli, const std::string& inputPath)
144146void fileTree (const std::string& inputPath) {
145147 auto packFile = PackFile::open (inputPath);
146148 if (!packFile) {
147- std::cerr << " Could not open the pack file at \" " << inputPath << " \" : it failed to load!" << std::endl ;
149+ throw vpkedit_load_error{ " Could not open the pack file at \" " + inputPath + " \" : it failed to load!" } ;
148150 }
149151 ::prettyPrintPackFile (packFile);
150152}
151153
152154// / Generate private/public key files
153155void generateKeyPair (const std::string& inputPath) {
154156 if (!VPK::generateKeyPairFiles (inputPath)) {
155- std::cerr << " Failed to generate public/private key files at \" " << inputPath << " .[private/public]key.vdf\" !" << std::endl;
156- return ;
157+ throw vpkedit_runtime_error{" Failed to generate public/private key files at \" " + inputPath + " .[private/public]key.vdf\" !" };
157158 }
158159 std::cout << " Generated private/public key files at \" " << inputPath << " .[private/public]key.vdf\" ." << std::endl;
159160 std::cout << " Remember to NEVER share a private key! The public key is fine to share." << std::endl;
@@ -165,15 +166,13 @@ void edit(const argparse::ArgumentParser& cli, const std::string& inputPath) {
165166 if (cli.is_used (ARG_S (OUTPUT))) {
166167 outputPath = cli.get (ARG_S (OUTPUT));
167168 if (!std::filesystem::exists (outputPath) || !std::filesystem::is_directory (outputPath)) {
168- std::cerr << " Output location must be an existing directory!" << std::endl;
169- return ;
169+ throw vpkedit_invalid_argument_error{" Output location must be an existing directory!" };
170170 }
171171 }
172172
173173 auto packFile = PackFile::open (inputPath);
174174 if (!packFile) {
175- std::cerr << " Could not open the pack file at \" " << inputPath << " \" : it failed to load!" << std::endl;
176- return ;
175+ throw vpkedit_load_error{" Could not open the pack file at \" " + inputPath + " \" : it failed to load!" };
177176 }
178177
179178 auto compressionMethod = ::compressionMethodStringToCompressionType (cli.get <std::string>(ARG_S (COMPRESSION_METHOD)));
@@ -183,9 +182,10 @@ void edit(const argparse::ArgumentParser& cli, const std::string& inputPath) {
183182 if (cli.is_used (ARG_L (REMOVE_FILE))) {
184183 auto path = cli.get (ARG_L (REMOVE_FILE));
185184 if (!packFile->removeEntry (path)) {
186- std::cerr
187- << " Unable to remove file at \" " << path << " \" from the pack file!\n "
188- << " Check the file exists in the pack file and the path is spelled correctly." << std::endl;
185+ throw vpkedit_runtime_error{
186+ " Unable to remove file at \" " + path + " \" from the pack file!\n "
187+ " Check the file exists in the pack file and the path is spelled correctly."
188+ };
189189 } else {
190190 std::cout << " Removed file at \" " << path << " \" from the pack file." << std::endl;
191191 }
@@ -194,9 +194,10 @@ void edit(const argparse::ArgumentParser& cli, const std::string& inputPath) {
194194 if (cli.is_used (ARG_L (REMOVE_DIR))) {
195195 auto path = cli.get (ARG_L (REMOVE_DIR));
196196 if (!packFile->removeDirectory (path)) {
197- std::cerr
198- << " Unable to remove directory at \" " << path << " \" from the pack file!\n "
199- << " Check the directory exists in the pack file and the path is spelled correctly." << std::endl;
197+ throw vpkedit_runtime_error{
198+ " Unable to remove directory at \" " + path + " \" from the pack file!\n "
199+ " Check the directory exists in the pack file and the path is spelled correctly."
200+ };
200201 } else {
201202 std::cout << " Removed directory at \" " << path << " \" from the pack file." << std::endl;
202203 }
@@ -205,9 +206,9 @@ void edit(const argparse::ArgumentParser& cli, const std::string& inputPath) {
205206 if (cli.is_used (ARG_L (ADD_FILE))) {
206207 auto args = cli.get <std::vector<std::string>>(ARG_L (ADD_FILE));
207208 if (!std::filesystem::exists (args[0 ])) {
208- std::cerr << " File at \" " << args[0 ] << " \" does not exist! Cannot add to pack file." << std::endl ;
209+ throw vpkedit_invalid_argument_error{ " File at \" " + args[0 ] + " \" does not exist! Cannot add to pack file." } ;
209210 } else if (!std::filesystem::is_regular_file (args[0 ])) {
210- std::cerr << " Path \" " << args[0 ] << " \" does not point to a file! Cannot add to pack file." << std::endl ;
211+ throw vpkedit_invalid_argument_error{ " Path \" " + args[0 ] + " \" does not point to a file! Cannot add to pack file." } ;
211212 } else {
212213 packFile->addEntry (args[1 ], args[0 ], {});
213214 std::cout << " Added file at \" " << args[0 ] << " \" to the pack file at path \" " << args[1 ] << " \" ." << std::endl;
@@ -217,9 +218,9 @@ void edit(const argparse::ArgumentParser& cli, const std::string& inputPath) {
217218 if (cli.is_used (ARG_L (ADD_DIR))) {
218219 auto args = cli.get <std::vector<std::string>>(ARG_L (ADD_DIR));
219220 if (!std::filesystem::exists (args[0 ])) {
220- std::cerr << " Directory at \" " << args[0 ] << " \" does not exist! Cannot add to pack file." << std::endl ;
221+ throw vpkedit_invalid_argument_error{ " Directory at \" " + args[0 ] + " \" does not exist! Cannot add to pack file." } ;
221222 } else if (!std::filesystem::is_directory (args[0 ])) {
222- std::cerr << " Path \" " << args[0 ] << " \" does not point to a directory! Cannot add to pack file." << std::endl ;
223+ throw vpkedit_invalid_argument_error{ " Path \" " + args[0 ] + " \" does not point to a directory! Cannot add to pack file." } ;
223224 } else {
224225 packFile->addDirectory (args[1 ], args[0 ]);
225226 std::cout << " Added directory at \" " << args[0 ] << " \" to the pack file at path \" " << args[1 ] << " \" ." << std::endl;
@@ -240,13 +241,15 @@ void sign(const argparse::ArgumentParser& cli, const std::string& inputPath) {
240241
241242 if (saveToDir) {
242243 std::cerr << " Warning: Signed VPKs that contain files will not be treated as signed by the Source engine!" << std::endl;
243- std::cerr << " Remove the " << ARG_S (SINGLE_FILE) << " / " << ARG_L (SINGLE_FILE) << " parameter for best results." << std::endl;
244+ std::cerr << " Rebuild the VPK and remove the " << ARG_S (SINGLE_FILE) << " / " << ARG_L (SINGLE_FILE) << " parameter for best results." << std::endl;
244245 }
245246
246247 auto vpk = VPK::open (inputPath);
247248 if (!vpk || !dynamic_cast <VPK*>(vpk.get ())->sign (signPath)) {
248- std::cerr << " Failed to sign VPK using private key file at \" " << signPath << " \" !" << std::endl;
249- std::cerr << " Check that the file exists and it contains both the private key and public key." << std::endl;
249+ throw vpkedit_runtime_error{
250+ " Failed to sign VPK using private key file at \" " + signPath + " \" !\n "
251+ " Check that the file exists and it contains both the private key and public key."
252+ };
250253 } else {
251254 std::cout << " Signed VPK using private key at \" " << signPath << " \" ." << std::endl;
252255 }
@@ -256,8 +259,7 @@ void sign(const argparse::ArgumentParser& cli, const std::string& inputPath) {
256259void verify (const argparse::ArgumentParser& cli, const std::string& inputPath) {
257260 auto packFile = PackFile::open (inputPath);
258261 if (!packFile) {
259- std::cerr << " Could not open the pack file at \" " << inputPath << " \" : it failed to load!" << std::endl;
260- return ;
262+ throw vpkedit_load_error{" Could not open the pack file at \" " + inputPath + " \" : it failed to load!" };
261263 }
262264
263265 if (cli.is_used (ARG_L (VERIFY_CHECKSUMS))) {
@@ -369,11 +371,10 @@ void pack(const argparse::ArgumentParser& cli, const std::string& inputPath) {
369371 packFile = WAD3::create (outputPath);
370372 }
371373 if (!packFile) {
372- std::cerr << " Failed to create pack file!" << std::endl;
373374 if (!noProgressBar) {
374375 bar->mark_as_completed ();
375376 }
376- return ;
377+ throw vpkedit_runtime_error{ " Failed to create pack file! " } ;
377378 }
378379
379380 packFile->addDirectory (" " , inputPath, [compressionMethod, compressionLevel, &preloadExtensions, saveToDir](const std::string& path) -> EntryOptions {
@@ -610,23 +611,32 @@ int main(int argc, const char* const* argv) {
610611 ::verify (cli, inputPath);
611612 }
612613 if (!foundAction) {
613- throw std::runtime_error {" No action taken! Add some arguments to clarify your intent." };
614+ throw vpkedit_invalid_argument_error {" No action taken! Add some arguments to clarify your intent." };
614615 }
615616 }
616617 } else if (cli.get <bool >(ARG_L (GEN_KEYPAIR))) {
617618 ::generateKeyPair (inputPath);
618619 } else {
619- throw std::runtime_error {" Given path does not exist!" };
620+ throw vpkedit_invalid_argument_error {" Given path does not exist!" };
620621 }
622+ } catch (const vpkedit_runtime_error& e) {
623+ std::cerr << e.what () << std::endl;
624+ return EXIT_FAILURE;
625+ } catch (const vpkedit_load_error& e) {
626+ std::cerr << e.what () << std::endl;
627+ return EXIT_FAILURE;
628+ } catch (const vpkedit_invalid_argument_error& e) {
629+ std::cerr << e.what () << ' \n ' << std::endl;
630+ std::cerr << " Run with --help to see more information about how to use this program." << std::endl;
631+ return EXIT_FAILURE;
621632 } catch (const std::exception& e) {
622633 if (argc > 1 ) {
623634 std::cerr << e.what () << ' \n ' << std::endl;
624- std::cerr << cli << std::endl;
635+ std::cerr << " Run with --help to see more information about how to use this program." << std::endl;
636+ return EXIT_FAILURE;
625637 } else {
626638 std::cout << cli << std::endl;
627639 }
628- return EXIT_FAILURE;
629640 }
630-
631641 return EXIT_SUCCESS;
632642}
0 commit comments