-
Notifications
You must be signed in to change notification settings - Fork 312
CLI and feedback enhancements #461
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
ecae36e
8be2c0c
76b3658
5dfe40d
2278318
084d9c6
ca0bd59
95c50a8
e0b6c2a
a177e4f
0d1cb02
7e74061
1274c94
6a952e3
a3497a3
5263452
ac94a69
f5c13b3
5ca8c1d
fed38ca
f141786
8f25328
59b35cc
ddc5711
a09392a
14fc152
3814eb7
72a2d64
86333a1
8f3c267
13be3fd
4b5ee62
475094a
01b4cc5
0ce28db
5a896d8
92f36e0
c28b210
02adbde
1a625af
d204d3e
66ca610
41b5a0f
b3d8e49
09ebe46
365245d
07be979
6e20cd0
351a7d4
ea55180
ff06c06
d13ff30
768fe14
7677f1c
79b71a9
abf7afe
6b96848
f2c7665
6301a02
e3bb107
7c2267a
b33cb3a
ce842bd
d927efd
cf923d2
1873091
93455d6
e995657
94dc3db
942a688
b37e464
6787ab1
793d446
6189051
366f82e
843ab5c
f5bada6
5e96528
5bf8d75
23d40e8
36829cb
27aca3b
3fab0be
d2ee494
647c156
615fb62
2a47358
3047e6a
7323702
0f5c691
7af2439
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,4 +14,7 @@ CMakeCache.txt | |
*.clst | ||
*.snap | ||
node_modules | ||
build | ||
build | ||
bin/ | ||
Docs/ | ||
.vscode |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,26 +29,31 @@ | |
* | ||
*/ | ||
|
||
#include <map> | ||
#include "buffer.h" | ||
#include <sys/stat.h> | ||
#include "liberror.h" | ||
#include <iostream> | ||
#include <fstream> | ||
|
||
#include "libcomm.h" | ||
#include "libuuu.h" | ||
#include "zip.h" | ||
#include "fat.h" | ||
#include "tar.h" | ||
#include <string.h> | ||
|
||
#include "bzlib.h" | ||
#include "stdio.h" | ||
#include <limits> | ||
#include "fat.h" | ||
#include "http.h" | ||
#include "string_man.h" | ||
#include "tar.h" | ||
#include "zip.h" | ||
#include "zstd.h" | ||
|
||
#include "libusb.h" | ||
#include <chrono> | ||
|
||
#include <stdio.h> | ||
#include <string.h> | ||
#include <sys/stat.h> | ||
|
||
#include <fstream> | ||
#include <iostream> | ||
#include <limits> | ||
#include <map> | ||
|
||
#ifdef WIN32 | ||
#define stat_os _stat64 | ||
#elif defined(__APPLE__) | ||
|
@@ -63,10 +68,51 @@ static map<string, shared_ptr<FileBuffer>> g_filebuffer_map; | |
static mutex g_mutex_map; | ||
static bool g_small_memory = true; | ||
|
||
// [what is the point/value of this value?] | ||
#define MAGIC_PATH '>' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mark avoid dead loop when search parent path |
||
|
||
string g_current_dir = ">"; | ||
|
||
static map<string, bool> warned_empty_files; | ||
|
||
/** | ||
* @brief Logs a warning if the specified file is empty | ||
* @details | ||
* This situation (opening an empty file) is somewhat common on Windows since builds typically | ||
* are run on Linux and such builds typically create link files which are convenient on Linux, | ||
* but when transferred to Windows are useless empty files, and processing an empty file at least | ||
* sometimes results in a hang at install time. This warning can be very helpful to a user | ||
* confused by the hang. | ||
* | ||
* Would be nice to use the logging facility, but it's at the app level; not accessible here. | ||
* Maybe should move the logging facility to the lib level. | ||
*/ | ||
static void warn_if_empty_file(string filename) | ||
{ | ||
// don't know what the > prefix means, but it's problematic here; remove it | ||
if (filename[0] == MAGIC_PATH) | ||
{ | ||
filename = filename.substr(1); | ||
} | ||
|
||
// only warn once per file since annoying to warn for the same file multiple times | ||
if (warned_empty_files.find(filename) != warned_empty_files.end()) return; | ||
warned_empty_files[filename] = true; | ||
|
||
// opening here shouldn't fail since should have been tested for existence already | ||
ifstream file(filename); | ||
if (!file.is_open()) { | ||
cerr << "INTERNAL ERROR: Could not open file to validate for empty: " << filename << std::endl; | ||
return; | ||
} | ||
|
||
bool is_empty = file.peek() == std::ifstream::traits_type::eof(); | ||
if (is_empty) | ||
{ | ||
cerr << "Warning: Empty input file: " << filename << "; maybe it's a link file accessed in Windows" << endl; | ||
} | ||
} | ||
|
||
void set_current_dir(const string &dir) | ||
{ | ||
g_current_dir = MAGIC_PATH; | ||
|
@@ -128,6 +174,9 @@ int DataBuffer::ref_other_buffer(std::shared_ptr<FileBuffer> p, size_t offset, s | |
return 0; | ||
}; | ||
|
||
/** | ||
* @brie Base class for FS things [whatever 'FS' means/is]. | ||
*/ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove [...] |
||
class FSBasic | ||
{ | ||
public: | ||
|
@@ -143,55 +192,86 @@ class FSBasic | |
virtual std::shared_ptr<FragmentBlock> ScanCompressblock(const string& /*backfile*/, size_t& /*input_offset*/, size_t& /*output_offset*/) { return NULL; }; | ||
virtual int PreloadWorkThread(shared_ptr<FileBuffer>outp); | ||
|
||
virtual int split(const string &filename, string *outbackfile, string *outfilename, bool dir=false) | ||
{ | ||
string path = str_to_upper(filename); | ||
/** | ||
* @brief Splits a file system path into directory and final name parts | ||
* @param path Input path | ||
* @param[out] dir_part Directory path info from input path | ||
* @param[out] name_part Final name part from input path | ||
* @param dir [what does this mean/imply?] | ||
* @return 0 for success; -1 for error | ||
* @details | ||
* If no/blank m_ext: | ||
* If dir: | ||
* Load dir_part with directory path part of path; >./ if none | ||
* Load name_part with file name part of path; blank if none | ||
* Else: | ||
* Load dir_part with input path | ||
* Else: | ||
* ext = m_ext | ||
* Append slash to ext if !dir | ||
* Find last ext in path | ||
* If not found: fail | ||
* Load dir_part with path up to and including ext | ||
* Load name_part with path after found ext | ||
* @example | ||
* path:"f", m_ext:"", !dir ==> ">./", "f" | ||
* path:"d/f", m_ext:"", !dir ==> "d", "f" | ||
* path:"d/", m_ext:"", !dir ==> "d", "" | ||
* path:"f", m_ext:"z", !dir ==> error | ||
* path:"d/z/f", m_ext:"z", !dir ==> "d/z", "f" | ||
* path:"d/z/", m_ext:"z", !dir ==> "d/z", "" | ||
* @note | ||
* Passing a bool like dir is bad style since it only controls flow. | ||
*/ | ||
virtual int split(const string &path, string *dir_part, string *name_part, bool dir=false) | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use seperate patch to change outbackfile-> dir_part, outfilename -> filename_part |
||
string upper_path = str_to_upper(path); | ||
if (m_ext == nullptr || strlen(m_ext) == 0) | ||
{ | ||
if(dir) | ||
{ | ||
size_t pos = path.rfind("/"); | ||
size_t pos = upper_path.rfind("/"); | ||
if(pos == string::npos) | ||
{ | ||
*outbackfile = MAGIC_PATH; | ||
*outbackfile += "./"; | ||
*outfilename = filename; | ||
*dir_part = MAGIC_PATH; | ||
*dir_part += "./"; | ||
*name_part = path; | ||
} else { | ||
*outbackfile = filename.substr(0, pos); | ||
if(filename.size() >= pos + 1) | ||
*outfilename = filename.substr(pos + 1); | ||
*dir_part = path.substr(0, pos); | ||
if(path.size() >= pos + 1) | ||
*name_part = path.substr(pos + 1); | ||
else | ||
outfilename->clear(); | ||
name_part->clear(); | ||
} | ||
}else | ||
{ | ||
*outbackfile = filename; | ||
*dir_part = path; | ||
} | ||
return 0; | ||
} | ||
|
||
string ext = m_ext; | ||
if(!dir) | ||
ext += "/"; | ||
size_t pos = path.rfind(ext); | ||
size_t pos = upper_path.rfind(ext); | ||
if (pos == string::npos) | ||
{ | ||
string err = "can't find ext name in path: "; | ||
err += filename; | ||
string err = "Expected '" + ext + "' in path '" + path + "'"; | ||
set_last_err_string(err); | ||
return -1; | ||
} | ||
|
||
*outbackfile = filename.substr(0, pos + strlen(m_ext)); | ||
*dir_part = path.substr(0, pos + strlen(m_ext)); | ||
|
||
if(filename.size() >= pos + strlen(m_ext) + 1) | ||
*outfilename = filename.substr(pos + strlen(m_ext) + 1); | ||
if(path.size() >= pos + strlen(m_ext) + 1) | ||
*name_part = path.substr(pos + strlen(m_ext) + 1); | ||
else | ||
outfilename->clear(); | ||
name_part->clear(); | ||
return 0; | ||
} | ||
|
||
protected: | ||
FSBasic() {} // enforce that this class is abstract base; only creatable via a superclass | ||
const char * m_ext = nullptr; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one should be sperate patch |
||
const char * m_Prefix = nullptr; | ||
public: | ||
|
@@ -718,20 +798,16 @@ static class FS_DATA | |
} | ||
int load(const string &filename, shared_ptr<FileBuffer> p) | ||
{ | ||
for (size_t i = 0; i < m_pFs.size(); i++) | ||
for (auto& fs : m_pFs) | ||
{ | ||
string back, fn; | ||
if (m_pFs[i]->split(filename, &back, &fn) == 0) { | ||
if (m_pFs[i]->load(back, fn, p) == 0) | ||
if (fs->split(filename, &back, &fn) == 0) { | ||
if (fs->load(back, fn, p) == 0) | ||
return 0; | ||
} | ||
} | ||
|
||
string err; | ||
err = "fail open file: "; | ||
err += filename; | ||
set_last_err_string(err); | ||
return -1; | ||
return set_last_err_string("Unable to open file: " + filename); | ||
} | ||
}g_fs_data; | ||
|
||
|
@@ -914,7 +990,10 @@ bool FSCompressStream::exist(const string &backfile, const string &filename) | |
return false; | ||
|
||
if (filename == "*") | ||
{ | ||
warn_if_empty_file(backfile); | ||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
|
@@ -1175,32 +1254,35 @@ uint64_t get_file_timesample(string filename) | |
return time; | ||
} | ||
|
||
/** | ||
* [what does this do?] | ||
* @param filename File system path | ||
* @param async TBD | ||
* @details | ||
* As a side-effect, this conforms filename by stripping quotes and if doesn't start with | ||
* MAGIC_PATH prepending g_current_dir and then replacing backslashes with forward. | ||
* @note | ||
* The side-effect should be eliminated since it adds to cognative load. | ||
*/ | ||
shared_ptr<FileBuffer> get 3D11 _file_buffer(string filename, bool async) | ||
{ | ||
filename = remove_quota(filename); | ||
|
||
filename = strip_quotes(filename); | ||
if (!filename.empty() && filename[0] != MAGIC_PATH) | ||
{ | ||
if (filename == "..") | ||
filename = g_current_dir.substr(0, g_current_dir.size() - 1); | ||
else | ||
filename = g_current_dir + filename; | ||
} | ||
string_man::replace(filename, "\\", "/"); | ||
|
||
string_ex path; | ||
path += filename; | ||
|
||
path.replace('\\', '/'); | ||
|
||
filename = path; | ||
|
||
bool find; | ||
bool found; | ||
{ | ||
std::lock_guard<mutex> lock(g_mutex_map); | ||
find = (g_filebuffer_map.find(filename) == g_filebuffer_map.end()); | ||
found = (g_filebuffer_map.find(filename) == g_filebuffer_map.end()); | ||
} | ||
|
||
if (find) | ||
if (found) | ||
{ | ||
shared_ptr<FileBuffer> p(new FileBuffer); | ||
|
||
|
@@ -1383,6 +1465,9 @@ int FileBuffer::ref_other_buffer(shared_ptr<FileBuffer> p, size_t offset, size_t | |
return 0; | ||
} | ||
|
||
/** | ||
* [what does this do?] | ||
*/ | ||
int FileBuffer::reload(string filename, bool async) | ||
{ | ||
if(async) { | ||
|
@@ -1803,10 +1888,16 @@ int FileBuffer::unmapfile() | |
return 0; | ||
} | ||
|
||
bool check_file_exist(string filename, bool /*start_async_load*/) | ||
bool path_exists(const string& path) | ||
{ | ||
struct stat_os st; | ||
return stat_os(path.c_str(), &st) == 0; | ||
} | ||
|
||
int verify_file_exist(string filename) | ||
{ | ||
string_ex fn; | ||
fn += remove_quota(filename); | ||
fn += strip_quotes(filename); | ||
string_ex path; | ||
if (!fn.empty() && fn[0] != MAGIC_PATH) | ||
{ | ||
|
@@ -1823,7 +1914,13 @@ bool check_file_exist(string filename, bool /*start_async_load*/) | |
|
||
if (path.empty()) | ||
path += "./"; | ||
return g_fs_data.exist(path); | ||
|
||
bool exists = g_fs_data.exist(path); | ||
if (!exists) | ||
{ | ||
return set_last_err_string("File not found: " + filename); | ||
} | ||
return 0; | ||
} | ||
|
||
#ifdef WIN32 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Create sperate patch for .gitignore file