--- /dev/null
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
+
--- /dev/null
+#include "reidoscl.hpp"
+#include <QApplication>
+
+class UpdateHandler{
+public:
+ UpdateHandler(ReProgramArgs* globalArgs);
+public:
+ int run();
+ void help(){
+ m_globalArgs->help(NULL);
+ m_updateArgs->help(NULL);
+ }
+private:
+ ReProgramArgs* m_globalArgs;
+ ReProgramArgs* m_updateArgs;
+};
+/**
+ * Constructor.
+ *
+ * @param globalArgs the global arguments (useful for all modes)
+ */
+UpdateHandler::UpdateHandler(ReProgramArgs* globalArgs) :
+ m_globalArgs(globalArgs),
+ m_updateArgs(NULL){
+ m_updateArgs = new ReProgramArgs(
+ I18N::s2b(
+ QObject::tr("usage:") + "$0 <global_opts> sy(nchronize) <options> <source> <target>\n"
+ + QObject::tr("Copies newer and missing files from <source> to <target>") + "\n"
+ + QObject::tr("<source>: the source directory. This directory is never changed") + "\n"
+ + QObject::tr("If <source> ends with the path separator the files of <source> will be copied directly to <target>") + "\n"
+ + QObject::tr("Otherwise the node of <source> will be a subdirectory of <target>") + "\n"
+ + QObject::tr("Examples:") + "\n"
+ + "<source>: /home/ <target>: "
+ + QObject::tr("/trg /home/abc.txt will be copied to /trg/abc.txt") + "\n"
+ + "<source>: /home <target>:"
+ + QObject::tr("/trg /home/abc.txt will be copied to /trg/home/abc.txt") + "\n"
+ + "<target>: "
+ + QObject::tr("the target directory")
+ ),
+ "$0 up -p *,*.txt,*.odt --dir-patterns=*,.git,.* /home /backup\n"
+ "$0 update --file-pattern=*,-*.bak,-*~ -P *,-*cache* /work crypt:/media/nas"
+ );
+ m_updateArgs->addString("filePattern", I18N::s2b(
+ QObject::tr("a comma separated list of file patterns to include/exclude files to copy.") + "\n"
+ + QObject::tr("An exclude pattern begins with '-'. Placeholder is '*' (for any string)") + "\n"
+ + QObject::tr("Examples:")
+ ) + "\n"
+ "--file-pattern=*,-*.bak\n"
+ "-p *.txt,*.doc,*.odt",
+ 'p', "file-pattern", false, "*");
+ m_updateArgs->addString("dirPattern", I18N::s2b(
+ QObject::tr("a comma separated list of directory patterns to include/exclude directories from processing.")
+ + "\n"
+ + QObject::tr("An exclude pattern begins with '-'. Placeholder is '*' (for any string)") + "\n"
+ + QObject::tr("Examples:") + "\n"
+ + "--dir-pattern=;*;-.cache\n"
+ + "-P *,-.git,.*"),
+ 'P', "dir-pattern", false, "*");
+ m_updateArgs->setProgramName(globalArgs->programName());
+ m_updateArgs->init(globalArgs->argCount(), globalArgs->args(), false);
+}
+
+int UpdateHandler::run()
+{
+ int rc = 0;
+ if (m_updateArgs->argCount() < 2)
+ m_updateArgs->help(I18N::s2b(QObject::tr("too few arguments")).constData());
+ else {
+
+ }
+ //ReFileSystem*
+ return rc;
+}
+
+/**
+ * Handles the mode "help".
+ *
+ * @param args the program arguments
+ */
+void handleHelp(ReProgramArgs& args){
+ QByteArray arg0 = args.shift();
+ args.help(NULL);
+ if (QByteArray("update").startsWith(arg0)){
+ UpdateHandler handler(&args);
+ handler.help();
+ } else if (QByteArray("help").startsWith(arg0)){
+ printf("%s help <mode>\n%s%s\n", args.programName(),
+ ReProgramArgs::PREFIX_LINE_OPTION,
+ I18N::s2b(QObject::tr("prints a description of the usage of <mode>")).constData());
+ } else {
+ printf("+++ %s\n",
+ I18N::s2b(QObject::tr("unknown <mode>:") + " " + arg0).constData());
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+ ReProgramArgs args(
+ QObject::tr("Usage:") + " $0 <opts> <mode> <mode_opts> <mode_params>\n"
+ + "<mode>:\n"
+ + "c(ompare) " + QObject::tr("compares two directories") + "\n"
+ + "h(elp) " + QObject::tr("shows a help text and examples") + "\n"
+ + "sm(ooth) " + QObject::tr("superflous files on target will be removed") + "\n"
+ + "u(pdate) " + QObject::tr("newer or missing files will be copied from source to target"),
+ "$0 --verbose-mode=summary c /home /opt/backup/home\n"
+ "$0 help update\n"
+ "$0 -v upd --dir-pattern=;*;-cache --file-pattern=;*.txt;*.doc /home /opt /media/backup"
+ );
+ int rc = 0;
+ try {
+ args.init(argc, argv);
+ QByteArray arg0;
+ if (args.argCount() < 1){
+ args.help(I18N::s2b(QObject::tr("missing <mode>")).constData());
+ rc = 1;
+ } else if (QByteArray("help").startsWith(arg0 = args.shift())){
+ handleHelp(args);
+ } else if (QByteArray("update").startsWith(arg0)){
+ UpdateHandler handler (&args);
+ rc = handler.run();
+ } else if (QByteArray("smooth").startsWith(arg0)){
+ UpdateHandler handler (&args);
+ rc = handler.run();
+ } else{
+ args.help((I18N::s2b(QObject::tr("unknown <mode>:")) + " " + arg0).constData());
+ rc = 1;
+ }
+ } catch( ReOptionException e){
+ args.help(NULL, true, stdout);
+ rc = 2;
+ }
+ // a.exec();
+ return rc;
+}
--- /dev/null
+/*
+ * Licence:
+ * You can use and modify this file without any restriction.
+ * There is no warranty.
+ * You also can use the licence from http://www.wtfpl.net/.
+ * The original sources can be found on https://github.com/republib.
+*/
+
+
+#ifndef REIDOSCMDLINE_HPP
+#define REIDOSCMDLINE_HPP
+#include "base/rebase.hpp"
+#include "os/reos.hpp"
+#include "gui/regui.hpp"
+
+#endif // REIDOSCMDLINE_HPP
+
--- /dev/null
+QT += core gui
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+TARGET = reidoscl
+CONFIG += console
+CONFIG -= app_bundle
+
+TEMPLATE = app
+
+INCLUDEPATH += . ../..
+
+SOURCES += \
+ ../../gui/ReEdit.cpp \
+ ../../gui/ReStateStorage.cpp \
+ ../../gui/ReSettings.cpp \
+ ../../gui/ReFileTree.cpp \
+ ../../gui/ReGuiValidator.cpp \
+ ../../base/ReMatcher.cpp \
+ ../../base/ReFile.cpp \
+ ../../base/ReStringUtils.cpp \
+ ../../base/ReRandomizer.cpp \
+ ../../os/ReFileSystem.cpp \
+ ../../os/ReCryptFileSystem.cpp \
+ ../../base/ReLogger.cpp \
+ ../../base/ReQStringUtils.cpp \
+ ../../base/ReFileUtils.cpp \
+ ../../base/ReException.cpp \
+ ../../base/ReProgramArgs.cpp \
+ reidoscl.cpp
+
+HEADERS += ../../base/rebase.hpp \
+ ../../gui/regui.hpp \
+ ../../gui/ReEdit.hpp \
+ ../../gui/ReStateStorage.hpp \
+ ../../gui/ReSettings.hpp \
+ ../../base/ReStringUtils.hpp \
+ ../../base/ReQStringUtils.hpp \
+ ../../base/ReException.hpp \
+ ../../os/reos.hpp
+ reidoscl.hpp
if (strstr(examples, "$0") == NULL)
m_examples = QByteArray(examples).split('\n');
else {
- QByteArray line;
- line = examples;
- line.replace("$0", m_program);
- m_examples = line.split('\n');
+ m_examples = QByteArray(examples).split('\n');
}
}
}
m_lastError() {
m_usage = I18N::s2b(usageString).split('\n');
if (! examples.isEmpty()) {
- m_examples = I18N::s2b(examples.replace("$0", QString(m_program))).split('\n');
+ m_examples = I18N::s2b(examples).split('\n');
}
}
/** @brief Destructor.
m_usage.append(usage[ix]);
}
+/**
+ * Sets the program name.
+ *
+ * @param program the program name
+ */
+void ReProgramArgs::setProgramName(const QByteArray& program){
+ m_program = program;
+}
+
+/**
+ * Gets the first program argument and remove it from the other args.
+ *
+ * @return "": no more arguments<br>
+ * the first argument
+ */
+QByteArray ReProgramArgs::shift()
+{
+ QByteArray rc;
+ if (m_argCount > 0){
+ rc = m_args[0];
+ m_argCount--;
+ m_args++;
+ }
+ return rc;
+}
+
/**
* Converts a type into a string.
*
return rc;
}
+/**
+ * Returns the argument vector (without options).
+ *
+ * @return the argument vector
+ */
+const char** ReProgramArgs::args() const
+{
+ return m_args;
+}
+
/** @brief Returns the count of arguments (without options).
*
* @return the count of arguments
}
lines.append(line.constData());
line.resize(0);
- line.append(PREFIX_LINE_OPTION).append(opt->m_description);
- lines.append(line.constData());
- line.resize(0);
+ QByteArrayList desc = opt->m_description.split('\n');
+ QByteArrayList::const_iterator it;
+ for (it = desc.cbegin(); it != desc.cend(); ++it){
+ line.resize(0);
+ line.append(PREFIX_LINE_OPTION).append(*it).append('\n');
+ lines.append(line);
+ }
}
if (m_examples.count() > 0) {
lines.append(I18N::s2b(QObject::tr("Example(s):")));
}
}
-/** @brief Initializes the options from the program arguments.
+/** Initializes the options from the program arguments.
*
* While arguments are preceded by an '-' they will be treated as options.
* The rest of arguments are stored for retrieving with <code>getArg()</code>.
*
- * @param argc The count of program arguments (inclusive options).
- * @param argv The argument vector.
+ * @param argc the count of program arguments (inclusive options)
+ * @param argv the argument vector
+ * @param hasProgram <code>true</code>: the first argument is the program name
*
* @throws ReException
*/
-void ReProgramArgs::init(int argc, const char* argv[]) {
- m_program = argv[0];
- argv++;
- argc--;
-
+void ReProgramArgs::init(int argc, const char* argv[], bool hasProgram) {
+ if (hasProgram){
+ m_program = argc <= 0 ? "" : ReFileUtils::nodeOf(argv[0]);
+ argv++;
+ argc--;
+ }
while (argc > 0 && argv[0][0] == '-') {
if (argv[0][1] == '-')
analyseLong(argv[0] + 2);
argv++;
}
m_argCount = argc;
- m_args = (const char**) argv;
+ m_args = argv;
+ for (int ii = 0; ii < m_usage.length(); ii++){
+ m_usage[ii].replace("$0", m_program);
+ }
+ QByteArray line;
+ for (int ii = 0; ii < m_examples.length(); ii++){
+ line = m_examples[ii];
+ m_examples[ii] = line.replace("$0", m_program);
+ }
}
/** @brief Returns the program name.
* <p>The connection between definition and retrieval are names.</p>
*/
class ReProgramArgs {
+public:
static const char* PREFIX_LINE_OPTION;
static QByteArray UNDEFINED_STRING;
public:
const char* longOpt, bool mayBeEmpty, const char* defaultVal);
int argCount() const;
const char* arg(size_t index) const;
+ const char** args() const;
bool getBool(const char* name);
int getInt(const char* name);
const char* getString(const char* name, QByteArray& buffer);
void help(const char* message, bool issueLastError,
QByteArrayList& lines) const;
- void help(const char* message, bool issueLastError, FILE* stream) const;
- void init(int argc, const char* argv[]);
+ void help(const char* message, bool issueLastError = false, FILE* stream = stdout) const;
+ void init(int argc, const char* argv[], bool hasProgram);
+ inline void init(int argc, char* argv[]){
+ return init(argc, (const char**) argv, true);
+ }
const char* programName() const;
void setLastError(const char* message);
void setLastError(const QByteArray& message);
void setUsage(const char* usage[]);
+ void setProgramName(const QByteArray& program);
+ QByteArray shift();
const char* typeToString(DataType dataType);
private:
void addProperties(const char*name, const char* description, char shortOpt,
* Removes end of line characters if any.
*
* @param text text to inspect
- * @return <code>text</code> without trailing '\\n' and/or '\\r'
+ * @param cc character to remove. If '\\n' also '\\r' will be removed
+ * @return <code>text</code> without trailing <code>cc</code>
*/
-ReString ReQStringUtils::chomp(const ReString& text) {
+ReString ReQStringUtils::chomp(const ReString& text, char cc) {
int last = text.length() - 1;
- while (last >= 0 && (text[last] == '\n' || text[last] == '\r')) {
- last--;
+ if (last < 0)
+ return text;
+ else {
+ if (cc != '\n'){
+ return text.at(last) == cc ? text.mid(0, last) : text;
+ } else {
+ while (last >= 0 && (text[last] == '\n' || text[last] == '\r')) {
+ last--;
+ }
+ return last == text.length() - 1 ? text : text.left(last + 1);
+ }
}
- return last == text.length() - 1 ? text : text.left(last + 1);
}
/**
*/
class ReQStringUtils {
public:
- static ReString chomp(const ReString& text);
+ static ReString chomp(const ReString& text, char cc = '\n');
static int countOf(const QString& value, QChar toFind, int start = 0);
static QString& ensureLastChar(QString& value, QChar lastChar);
static int lengthOfDate(const ReString& text, int start = 0, QDate* value =
args.addInt("intArg", "integer arg", 'i', "int-arg", 99);
args.addString("stringArg", "string argument", 's', "string-arg", true, "");
const char* arguments[] = { "example" };
- args.init(1, arguments);
+ args.init2(1, arguments);
checkF(args.getBool("boolArg"));
checkEqu(99, args.getInt("intArg"));
QByteArray buffer = "123";
"-t", "-f",
NULL
};
- args.init(9, arguments);
+ args.init2(9, arguments);
checkT(args.getBool("trueArg"));
checkF(args.getBool("falseArg"));
checkT(args.getBool("trueArg2"));
"--arg2=3355",
NULL
};
- args.init(4, arguments);
+ args.init2(4, arguments);
checkEqu(2244, args.getInt("intArg"));
checkEqu(3355, args.getInt("intArg2"));
NULL
};
try {
- args2.init(2, arguments2);
+ args2.init2(2, arguments2);
error("exception expected: missing parameter");
} catch(ReOptionException e){
checkT(e.getMessage().indexOf("arg2") > 0);
"--arg3=",
NULL
};
- args.init(5, arguments);
+ args.init2(5, arguments);
QByteArray buffer;
checkEqu("wow", args.getString("stringArg", buffer));
checkEqu("1 2 3", args.getString("stringArg2", buffer));
NULL
};
try {
- args2.init(2, arguments2);
+ args2.init2(2, arguments2);
error("exception expected: missing parameter");
} catch(ReOptionException e){
checkT(e.getMessage().indexOf("arg2") > 0);
NULL
};
try {
- args3.init(3, arguments3);
+ args3.init2(3, arguments3);
error("exception expected: empty string is not allowed");
} catch(ReOptionException e){
checkT(e.getMessage().indexOf("arg2") > 0);