infoedit
Change-Id: I4d08ee17075f0b0e205817be7dcdb417073df43a
refs: #2964
diff --git a/README.md b/README.md
index 92c7c57..5ecec83 100644
--- a/README.md
+++ b/README.md
@@ -26,6 +26,7 @@
install_NFD - install NFD (https://github.com/named-data/NFD)
install_ndntraffic - install ndn-traffic-generator (https://github.com/named-data/ndn-traffic-generator)
install_ndntools - install ndn-tools (https://github.com/named-data/ndn-tools)
+ install_infoedit - install infoedit
install_all - do all of the above
help - print this message and exit
diff --git a/install_apps.py b/install_apps.py
index 523a1a7..ccf938d 100755
--- a/install_apps.py
+++ b/install_apps.py
@@ -16,6 +16,8 @@
print " install_NFD - install NFD (named-data/NFD)"
print " install_ndntraffic - install ndn-traffic-generator (named-data/ndn-traffic-generator)"
print " install_ndntools - install ndn-tools (named-data/ndn-tools)"
+ print " install_repo - install repo-ng (named-data/repo-ng)"
+ print " install_infoedit - install infoedit"
print " install_all - do all of the above"
print " help - print this message and exit\n"
@@ -31,6 +33,8 @@
"install_NFD",
"install_ndntraffic",
"install_ndntools",
+ "install_repo",
+ "install_infoedit",
"install_all",
"help" ]
@@ -49,6 +53,8 @@
actionList.add("install_NFD")
actionList.add("install_ndntraffic")
actionList.add("install_ndntools")
+ actionList.add("install_repo")
+ actionList.add("install_infoedit")
module = __import__("setup_preparation_folder")
module.run()
module = __import__("install_dependencies")
@@ -68,6 +74,12 @@
if "install_ndntools" in actionList:
module = __import__("install_ndntools")
module.run()
+ if "install_repo" in actionList:
+ module = __import__("install_repo")
+ module.run()
+ if "install_infoedit" in actionList:
+ module = __import__("install_infoedit")
+ module.run()
print ""
else:
usage()
diff --git a/install_helpers/infoedit/README.md b/install_helpers/infoedit/README.md
new file mode 100644
index 0000000..df8a0e5
--- /dev/null
+++ b/install_helpers/infoedit/README.md
@@ -0,0 +1,90 @@
+A tool used to edit NFD configuration files
+===========================================
+
+This tool is majorly developed for use in NFD integration tests. However, it can also used to
+edit any INFO-formatted files.
+
+Each invocation of `infoedit` tool performs exactly one edit and the file is modified in place.
+To perform multiple edits, `infoedit` tool should be invoked multiple times on the same file.
+
+## Usage ##
+
+ infoedit [-f file] [-s|d|a|r path] [-v value]
+
+OPTIONS:
+
+* `-f file`: specifies a file to edit
+* `-s path`: specifies a property-tree path to modify
+* `-v value`: used with -s path, sets the value at the path
+* `-d path`: deletes all subtrees matching the path
+* `-a path`: adds a subtree at the path; the subtree is read from stdin
+* `-r path`: replaces a subtree at the path; equivalent to -d path followed by -a path
+
+## Sample command lines ##
+
+ ./infoedit -f nfd.conf -s general.user -v ndn.user
+ ./infoedit -f nfd.conf -s tables.strategy_choice./site -v /localhost/nfd/strategy/broadcast
+ ./infoedit -f nfd.conf -d tables.strategy_choice./
+ ./infoedit -f nfd.conf -d authorizations
+ ./infoedit -f nfd.conf -a rib.localhost_security <<<EOT
+ trust-anchor
+ {
+ type any
+ }
+ EOT
+
+### nfd.conf used in above sample ###
+
+ ; comment1
+
+ general ; comment2
+ {
+ user user ; comment3
+ group group
+ }
+
+ tables
+ {
+ strategy_choice
+ {
+ / /localhost/nfd/strategy/best-route
+ /site /localhost/nfd/strategy/broadcast
+ }
+ }
+
+ authorizations
+ {
+ authorize
+ {
+ certfile file1.cert
+ }
+ authorize
+ {
+ certfile file2.cert
+ }
+ }
+
+### nfd.conf after carrying out all commands in above sample ###
+
+ general
+ {
+ user ndn.user
+ group group
+ }
+ tables
+ {
+ strategy_choice
+ {
+ /site /localhost/nfd/strategy/broadcast
+ }
+ }
+ rib
+ {
+ localhost_security
+ {
+ trust-anchor
+ {
+ type any
+ }
+ }
+ }
\ No newline at end of file
diff --git a/install_helpers/infoedit/infoedit.cpp b/install_helpers/infoedit/infoedit.cpp
new file mode 100644
index 0000000..958b54f
--- /dev/null
+++ b/install_helpers/infoedit/infoedit.cpp
@@ -0,0 +1,186 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright 2015, Regents of the University of California.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
+ * file except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+#include "infoedit.hpp"
+#include <iostream>
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/variables_map.hpp>
+#include <boost/program_options/parsers.hpp>
+
+namespace infoedit {
+
+void
+InfoEditor::load(const std::string& fileName)
+{
+ std::ifstream input(fileName);
+ if (!input.good() || !input.is_open()) {
+ throw Error("Failed to open configuration file for parsing");
+ }
+
+ try {
+ boost::property_tree::info_parser::read_info(input, m_info);
+ }
+ catch (boost::property_tree::info_parser::info_parser_error& error) {
+ std::stringstream msg;
+ msg << "Failed to parse configuration file";
+ msg << " " << error.message() << " line " << error.line();
+ throw Error(msg.str());
+ }
+
+ input.close();
+}
+
+InfoEditor&
+InfoEditor::modify(const std::string& section, const std::string& value)
+{
+ m_info.put(section.c_str(), value.c_str());
+ return *this;
+}
+
+InfoEditor&
+InfoEditor::remove(const std::string& section)
+{
+ std::size_t pos = section.find_last_of(".");
+ if (pos == std::string::npos) {
+ m_info.erase(section.c_str());
+ }
+ else {
+ boost::optional<boost::property_tree::ptree&> child =
+ m_info.get_child_optional(section.substr(0, pos));
+ if (child) {
+ child->erase(section.substr(pos + 1));
+ }
+ }
+
+ return *this;
+}
+
+InfoEditor&
+InfoEditor::insert(const std::string& section, std::istream& stream)
+{
+ boost::property_tree::ptree pt;
+ read_info(stream, pt);
+
+ m_info.add_child(section.c_str(), pt);
+
+ return *this;
+}
+
+void
+InfoEditor::save(const std::string& fileName)
+{
+ std::ofstream output(fileName);
+ write_info(output, m_info);
+ output.close();
+}
+
+int
+main(int argc, char** argv)
+{
+ std::string configFile;
+ std::string sectionPath;
+ std::string value;
+
+ namespace po = boost::program_options;
+ po::options_description description("Usage\n"
+ " infoedit [-f file] [-s|d|a|r path] [-v value]\n"
+ "Options");
+
+ description.add_options()
+ ("help,h", "print this help message")
+ ("file,f", po::value<std::string>(&configFile), "the file to edit")
+ ("section,s", po::value<std::string>(§ionPath), "the section to modify")
+ ("value,v", po::value<std::string>(&value), "the value used to modify some section")
+ ("delete,d", po::value<std::string>(§ionPath), "the sub tree to delete")
+ ("add,a", po::value<std::string>(§ionPath), "adds a sub tree")
+ ("replace,r", po::value<std::string>(§ionPath), "replace the sub tree")
+ ;
+
+ po::variables_map vm;
+ try {
+ po::store(po::command_line_parser(argc, argv).options(description).run(), vm);
+ po::notify(vm);
+ }
+ catch (const std::exception& e) {
+ std::cerr << "ERROR: " << e.what()
+ << "\n"
+ << description;
+ return 1;
+ }
+
+ if (vm.count("help") > 0) {
+ std::cout << description;
+ return 0;
+ }
+
+ if (vm.count("file") == 0) {
+ std::cerr << "ERROR: the file to edit should be specified"
+ << "\n"
+ << description;
+ return 1;
+ }
+
+ InfoEditor editor;
+ try {
+ editor.load(configFile);
+ }
+ catch (const std::exception& e) {
+ std::cerr << "ERROR: " << e.what() << std::endl;
+ return 1;
+ }
+
+ try {
+ if (vm.count("section") > 0) {
+ if (vm.count("value") == 0) {
+ std::cerr << "ERROR: value must be specified" << std::endl;
+ return 1;
+ }
+
+ editor.modify(sectionPath, value);
+ }
+
+ if (vm.count("delete") > 0) {
+ editor.remove(sectionPath);
+ }
+
+ if (vm.count("add") > 0) {
+ editor.insert(sectionPath, std::cin);
+ }
+
+ if (vm.count("replace") > 0) {
+ editor.remove(sectionPath).insert(sectionPath, std::cin);
+ }
+ }
+ catch (...) {
+ return 1;
+ }
+
+ try {
+ editor.save(configFile);
+ }
+ catch (...) {
+ return 1;
+ }
+
+ return 0;
+}
+
+} // namespace infoedit
+
+int
+main(int argc, char** argv)
+{
+ return infoedit::main(argc, argv);
+}
diff --git a/install_helpers/infoedit/infoedit.hpp b/install_helpers/infoedit/infoedit.hpp
new file mode 100644
index 0000000..6217c03
--- /dev/null
+++ b/install_helpers/infoedit/infoedit.hpp
@@ -0,0 +1,60 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright 2015, Regents of the University of California.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
+ * file except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+#ifndef INTEGRATION_TESTS_INSTALL_HELPERS_INFOEDIT_INFOEDIT_HPP
+#define INTEGRATION_TESTS_INSTALL_HELPERS_INFOEDIT_INFOEDIT_HPP
+
+#include <fstream>
+#include <iostream>
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/info_parser.hpp>
+
+namespace infoedit {
+
+class InfoEditor
+{
+public:
+ class Error : public std::runtime_error
+ {
+ public:
+ Error(const std::string& what)
+ : std::runtime_error(what)
+ {
+ }
+ };
+
+public:
+ void
+ load(const std::string& fileName);
+
+ InfoEditor&
+ modify(const std::string& section, const std::string& value);
+
+ InfoEditor&
+ remove(const std::string& section);
+
+ InfoEditor&
+ insert(const std::string& section, std::istream& stream);
+
+ void
+ save(const std::string& fileName);
+
+private:
+ boost::property_tree::ptree m_info;
+};
+
+} // namespace infoedit
+
+#endif // INTEGRATION_TESTS_INSTALL_HELPERS_INFOEDIT_INFOEDIT_HPP
diff --git a/install_helpers/install_infoedit.py b/install_helpers/install_infoedit.py
new file mode 100644
index 0000000..737f923
--- /dev/null
+++ b/install_helpers/install_infoedit.py
@@ -0,0 +1,16 @@
+#!/usr/bin/python2
+import os
+
+# Install infoedit
+def run():
+ print "\nINSTALLING infoedit"
+ print "***********************"
+ helper_path = os.path.dirname(os.path.realpath(__file__))
+ cwd_path = os.getcwd()
+ #print helper_path
+ #print cwd_path
+ os.chdir(helper_path)
+ os.chdir("infoedit")
+ os.system("g++ -o infoedit -std=c++0x infoedit.cpp $(pkg-config --cflags --libs libndn-cxx)")
+ os.system("sudo mv infoedit /usr/local/bin/")
+ os.chdir(cwd_path)