mirror of https://github.com/aria2/aria2
Save options directly specified for download in --save-session
This change makes --save-session save only options specified for download, more specifically, options in command-line, -i file and via RPC. The other options from conf file and default values are not saved. This will drastically decrease the size of session file.pull/73/head
parent
07d38e31ad
commit
4070113ef0
|
@ -51,7 +51,8 @@ Option::~Option() {}
|
|||
|
||||
Option::Option(const Option& option)
|
||||
: table_(option.table_),
|
||||
use_(option.use_)
|
||||
use_(option.use_),
|
||||
parent_(option.parent_)
|
||||
{}
|
||||
|
||||
Option& Option::operator=(const Option& option)
|
||||
|
@ -59,6 +60,7 @@ Option& Option::operator=(const Option& option)
|
|||
if(this != &option) {
|
||||
table_ = option.table_;
|
||||
use_ = option.use_;
|
||||
parent_ = option.parent_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
@ -85,18 +87,34 @@ void Option::put(const Pref* pref, const std::string& value) {
|
|||
}
|
||||
|
||||
bool Option::defined(const Pref* pref) const
|
||||
{
|
||||
return bitfield::test(use_, use_.size()*8, pref->i) ||
|
||||
(parent_ && parent_->defined(pref));
|
||||
}
|
||||
|
||||
bool Option::definedLocal(const Pref* pref) const
|
||||
{
|
||||
return bitfield::test(use_, use_.size()*8, pref->i);
|
||||
}
|
||||
|
||||
bool Option::blank(const Pref* pref) const
|
||||
{
|
||||
return !defined(pref) || table_[pref->i].empty();
|
||||
if(bitfield::test(use_, use_.size()*8, pref->i)) {
|
||||
return table_[pref->i].empty();
|
||||
} else {
|
||||
return !parent_ || parent_->blank(pref);
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& Option::get(const Pref* pref) const
|
||||
{
|
||||
return table_[pref->i];
|
||||
if(bitfield::test(use_, use_.size()*8, pref->i)) {
|
||||
return table_[pref->i];
|
||||
} else if(parent_) {
|
||||
return parent_->get(pref);
|
||||
} else {
|
||||
return A2STR::NIL;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t Option::getAsInt(const Pref* pref) const {
|
||||
|
@ -153,4 +171,14 @@ void Option::merge(const Option& option)
|
|||
}
|
||||
}
|
||||
|
||||
void Option::setParent(const SharedHandle<Option>& parent)
|
||||
{
|
||||
parent_ = parent;
|
||||
}
|
||||
|
||||
const SharedHandle<Option>& Option::getParent() const
|
||||
{
|
||||
return parent_;
|
||||
}
|
||||
|
||||
} // namespace aria2
|
||||
|
|
29
src/Option.h
29
src/Option.h
|
@ -40,6 +40,8 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "SharedHandle.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
struct Pref;
|
||||
|
@ -48,6 +50,7 @@ class Option {
|
|||
private:
|
||||
std::vector<std::string> table_;
|
||||
std::vector<unsigned char> use_;
|
||||
SharedHandle<Option> parent_;
|
||||
public:
|
||||
Option();
|
||||
~Option();
|
||||
|
@ -55,29 +58,41 @@ public:
|
|||
Option& operator=(const Option& option);
|
||||
|
||||
void put(const Pref* pref, const std::string& value);
|
||||
// Returns true if name is defined. Otherwise returns false.
|
||||
// Note that even if the value is a empty string, this method returns true.
|
||||
// Returns true if name is defined. Otherwise returns false. Note
|
||||
// that even if the value is a empty string, this method returns
|
||||
// true. If option is not defined in this object and parent_ is not
|
||||
// NULL, lookup parent_ to check |pref| is defined.
|
||||
bool defined(const Pref* pref) const;
|
||||
// Just like defined(), but this function does not lookup parent_.
|
||||
bool definedLocal(const Pref* pref) const;
|
||||
// Returns true if name is not defined or the value is a empty string.
|
||||
// Otherwise returns false.
|
||||
bool blank(const Pref* pref) const;
|
||||
// Returns option value for |pref|. If the |pref| is not defined in
|
||||
// this object, parent_ is looked up.
|
||||
const std::string& get(const Pref* pref) const;
|
||||
int32_t getAsInt(const Pref* pref) const;
|
||||
int64_t getAsLLInt(const Pref* pref) const;
|
||||
bool getAsBool(const Pref* pref) const;
|
||||
double getAsDouble(const Pref* pref) const;
|
||||
|
||||
// Removes |pref| from this object. This function does not modify
|
||||
// parent_.
|
||||
void remove(const Pref* pref);
|
||||
|
||||
// Removes all option values from this object. This function does
|
||||
// not modify parent_.
|
||||
void clear();
|
||||
|
||||
// Returns the option value table of this object. It does not
|
||||
// contain option values in parent_ and so forth.
|
||||
const std::vector<std::string>& getTable() const
|
||||
{
|
||||
return table_;
|
||||
}
|
||||
|
||||
// Copy option values defined in option to this option.
|
||||
// Copy option values defined in option to this option. parent_ is
|
||||
// left unmodified for this object.
|
||||
void merge(const Option& option);
|
||||
// Sets parent Option object for this object.
|
||||
void setParent(const SharedHandle<Option>& parent);
|
||||
const SharedHandle<Option>& getParent() const;
|
||||
};
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -112,7 +112,7 @@ bool writeOption(BufferedFile& fp, const SharedHandle<Option>& op)
|
|||
for(size_t i = 1, len = option::countOption(); i < len; ++i) {
|
||||
const Pref* pref = option::i2p(i);
|
||||
const OptionHandler* h = oparser->find(pref);
|
||||
if(h && h->getInitialOption() && op->defined(pref)) {
|
||||
if(h && h->getInitialOption() && op->definedLocal(pref)) {
|
||||
if(h->getCumulative()) {
|
||||
const std::string& val = op->get(pref);
|
||||
std::vector<std::string> v;
|
||||
|
|
18
src/main.cc
18
src/main.cc
|
@ -272,14 +272,16 @@ error_code::Value main(int argc, char* argv[])
|
|||
// command-line. If they are left, because op is used as a template
|
||||
// for new RequestGroup(such as created in RPC command), they causes
|
||||
// unintentional effect.
|
||||
op->remove(PREF_OUT);
|
||||
op->remove(PREF_FORCE_SEQUENTIAL);
|
||||
op->remove(PREF_INPUT_FILE);
|
||||
op->remove(PREF_INDEX_OUT);
|
||||
op->remove(PREF_SELECT_FILE);
|
||||
op->remove(PREF_PAUSE);
|
||||
op->remove(PREF_CHECKSUM);
|
||||
op->remove(PREF_GID);
|
||||
for(SharedHandle<Option> i = op; i; i = i->getParent()) {
|
||||
i->remove(PREF_OUT);
|
||||
i->remove(PREF_FORCE_SEQUENTIAL);
|
||||
i->remove(PREF_INPUT_FILE);
|
||||
i->remove(PREF_INDEX_OUT);
|
||||
i->remove(PREF_SELECT_FILE);
|
||||
i->remove(PREF_PAUSE);
|
||||
i->remove(PREF_CHECKSUM);
|
||||
i->remove(PREF_GID);
|
||||
}
|
||||
if(!op->getAsBool(PREF_ENABLE_RPC) && requestGroups.empty() &&
|
||||
!uriListParser) {
|
||||
global::cout()->printf("%s\n", MSG_NO_FILES_TO_DOWNLOAD);
|
||||
|
|
|
@ -175,6 +175,20 @@ void showCandidates
|
|||
|
||||
} // namespace
|
||||
|
||||
#ifdef __MINGW32__
|
||||
namespace {
|
||||
void optionNativeToUtf8(Option& op)
|
||||
{
|
||||
for(size_t i = 1, len = option::countOption(); i < len; ++i) {
|
||||
const Pref* pref = option::i2p(i);
|
||||
if(op.definedLocal(pref) && !util::isUtf8(op.get(pref))) {
|
||||
op.put(pref, nativeToUtf8(op.get(pref)));
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
#endif // __MINGW32__
|
||||
|
||||
void option_processing(Option& op, std::vector<std::string>& uris,
|
||||
int argc, char* argv[])
|
||||
{
|
||||
|
@ -213,9 +227,8 @@ void option_processing(Option& op, std::vector<std::string>& uris,
|
|||
exit(error_code::FINISHED);
|
||||
}
|
||||
}
|
||||
|
||||
oparser->parseDefaultValues(op);
|
||||
|
||||
SharedHandle<Option> confOption(new Option());
|
||||
oparser->parseDefaultValues(*confOption);
|
||||
if(!noConf) {
|
||||
std::string cfname =
|
||||
ucfname.empty() ?
|
||||
|
@ -230,7 +243,7 @@ void option_processing(Option& op, std::vector<std::string>& uris,
|
|||
}
|
||||
}
|
||||
try {
|
||||
oparser->parse(op, ss);
|
||||
oparser->parse(*confOption, ss);
|
||||
} catch(OptionHandlerException& e) {
|
||||
global::cerr()->printf(_("Parse error in %s"), cfname.c_str());
|
||||
global::cerr()->printf("\n%s", e.stackTrace().c_str());
|
||||
|
@ -254,24 +267,21 @@ void option_processing(Option& op, std::vector<std::string>& uris,
|
|||
}
|
||||
}
|
||||
// Override configuration with environment variables.
|
||||
overrideWithEnv(op, oparser, PREF_HTTP_PROXY, "http_proxy");
|
||||
overrideWithEnv(op, oparser, PREF_HTTPS_PROXY, "https_proxy");
|
||||
overrideWithEnv(op, oparser, PREF_FTP_PROXY, "ftp_proxy");
|
||||
overrideWithEnv(op, oparser, PREF_ALL_PROXY, "all_proxy");
|
||||
overrideWithEnv(op, oparser, PREF_NO_PROXY, "no_proxy");
|
||||
overrideWithEnv(*confOption, oparser, PREF_HTTP_PROXY, "http_proxy");
|
||||
overrideWithEnv(*confOption, oparser, PREF_HTTPS_PROXY, "https_proxy");
|
||||
overrideWithEnv(*confOption, oparser, PREF_FTP_PROXY, "ftp_proxy");
|
||||
overrideWithEnv(*confOption, oparser, PREF_ALL_PROXY, "all_proxy");
|
||||
overrideWithEnv(*confOption, oparser, PREF_NO_PROXY, "no_proxy");
|
||||
|
||||
// we must clear eof bit and seek to the beginning of the buffer.
|
||||
cmdstream.clear();
|
||||
cmdstream.seekg(0, std::ios::beg);
|
||||
// finaly let's parse and store command-iine options.
|
||||
op.setParent(confOption);
|
||||
oparser->parse(op, cmdstream);
|
||||
#ifdef __MINGW32__
|
||||
for(size_t i = 1, len = option::countOption(); i < len; ++i) {
|
||||
const Pref* pref = option::i2p(i);
|
||||
if(op.defined(pref) && !util::isUtf8(op.get(pref))) {
|
||||
op.put(pref, nativeToUtf8(op.get(pref)));
|
||||
}
|
||||
}
|
||||
optionNativeToUtf8(op);
|
||||
optionNativeToUtf8(*confOption);
|
||||
#endif // __MINGW32__
|
||||
} catch(OptionHandlerException& e) {
|
||||
global::cerr()->printf("%s", e.stackTrace().c_str());
|
||||
|
|
|
@ -17,6 +17,7 @@ class OptionTest:public CppUnit::TestFixture {
|
|||
CPPUNIT_TEST(testDefined);
|
||||
CPPUNIT_TEST(testBlank);
|
||||
CPPUNIT_TEST(testMerge);
|
||||
CPPUNIT_TEST(testParent);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
private:
|
||||
|
||||
|
@ -30,6 +31,7 @@ public:
|
|||
void testDefined();
|
||||
void testBlank();
|
||||
void testMerge();
|
||||
void testParent();
|
||||
};
|
||||
|
||||
|
||||
|
@ -93,4 +95,32 @@ void OptionTest::testMerge()
|
|||
CPPUNIT_ASSERT(!dest.defined(PREF_OUT));
|
||||
}
|
||||
|
||||
void OptionTest::testParent()
|
||||
{
|
||||
Option child;
|
||||
SharedHandle<Option> parent(new Option());
|
||||
parent->put(PREF_TIMEOUT, "100");
|
||||
child.put(PREF_DIR, "foo");
|
||||
CPPUNIT_ASSERT(!child.defined(PREF_TIMEOUT));
|
||||
CPPUNIT_ASSERT(!child.definedLocal(PREF_TIMEOUT));
|
||||
child.setParent(parent);
|
||||
CPPUNIT_ASSERT(child.defined(PREF_TIMEOUT));
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("100"), child.get(PREF_TIMEOUT));
|
||||
CPPUNIT_ASSERT_EQUAL((int32_t)100, child.getAsInt(PREF_TIMEOUT));
|
||||
CPPUNIT_ASSERT(!child.definedLocal(PREF_TIMEOUT));
|
||||
// blank
|
||||
CPPUNIT_ASSERT(!child.blank(PREF_DIR));
|
||||
child.put(PREF_DIR, "");
|
||||
CPPUNIT_ASSERT(child.blank(PREF_DIR));
|
||||
CPPUNIT_ASSERT(!child.blank(PREF_TIMEOUT));
|
||||
// override
|
||||
child.put(PREF_TIMEOUT, "200");
|
||||
CPPUNIT_ASSERT(child.defined(PREF_TIMEOUT));
|
||||
CPPUNIT_ASSERT(child.definedLocal(PREF_TIMEOUT));
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("200"), child.get(PREF_TIMEOUT));
|
||||
child.remove(PREF_TIMEOUT);
|
||||
CPPUNIT_ASSERT(child.defined(PREF_TIMEOUT));
|
||||
CPPUNIT_ASSERT(!child.definedLocal(PREF_TIMEOUT));
|
||||
}
|
||||
|
||||
} // namespace aria2
|
||||
|
|
Loading…
Reference in New Issue