[glom] Added the glom_create_from_example command-line utility.
- From: Murray Cumming <murrayc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glom] Added the glom_create_from_example command-line utility.
- Date: Mon, 10 Oct 2011 08:44:52 +0000 (UTC)
commit d74ca12563530246d8e87b96c9c454173a04ea3f
Author: Murray Cumming <murrayc murrayc com>
Date: Mon Oct 10 10:41:36 2011 +0200
Added the glom_create_from_example command-line utility.
* Makefile_libglom.am:
* glom/glom_create_from_example.cc: This command-line utility takes an
example .glom file, outputs a new non-example .glom file and puts the
example data, if any, in the database.
Right now, it assumes that you want self-hosting, so it creates the
database files locally.
This builds when libglom builds. It does not require the glom application.
ChangeLog | 12 ++
Makefile_libglom.am | 11 +
glom/glom_create_from_example.cc | 392 ++++++++++++++++++++++++++++++++++++++
glom/main.cc | 3 +-
4 files changed, 417 insertions(+), 1 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index aa374a8..0d45589 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
2011-10-10 Murray Cumming <murrayc murrayc com>
+ Added the glom_create_from_example command-line utility.
+
+ * Makefile_libglom.am:
+ * glom/glom_create_from_example.cc: This command-line utility takes an
+ example .glom file, outputs a new non-example .glom file and puts the
+ example data, if any, in the database.
+ Right now, it assumes that you want self-hosting, so it creates the
+ database files locally.
+ This builds when libglom builds. It does not require the glom application.
+
+2011-10-10 Murray Cumming <murrayc murrayc com>
+
Added Utils::get_file_*_without_extension().
* glom/application.[h|cc]: Moved get_file_uri_without_extension() to
diff --git a/Makefile_libglom.am b/Makefile_libglom.am
index 94c02ad..57c3abc 100644
--- a/Makefile_libglom.am
+++ b/Makefile_libglom.am
@@ -75,3 +75,14 @@ pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = glom/libglom/glom- GLOM_ABI_VERSION@.pc
+# Command-line tools:
+
+glom_commandline_ldadd = glom/libglom/libglom-$(GLOM_ABI_VERSION).la $(libglom_all_libs)
+glom_commandline_cppflags = $(glom_includes) $(LIBGLOM_CFLAGS) $(PYTHON_CPPFLAGS) $(BOOST_PYTHON_CFLAGS) $(glom_defines)
+
+bin_PROGRAMS = glom/glom_create_from_example
+
+glom_glom_create_from_example_SOURCES = glom/glom_create_from_example.cc
+glom_glom_create_from_example_LDADD = $(glom_commandline_ldadd)
+glom_glom_create_from_example_CPPFLAGS = $(glom_commandline_cppflags)
+
diff --git a/glom/glom_create_from_example.cc b/glom/glom_create_from_example.cc
new file mode 100644
index 0000000..cda42f0
--- /dev/null
+++ b/glom/glom_create_from_example.cc
@@ -0,0 +1,392 @@
+/* Glom
+ *
+ * Copyright (C) 2011 Openismus GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+71 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+// For instance:
+// glom_create_from_example /opt/gnome30/share/doc/glom/examples/example_music_collection.glom --output-path=/home/murrayc/ --output-name="something.glom"
+
+#include "config.h"
+
+#include <libglom/document/document.h>
+#include <libglom/connectionpool.h>
+#include <libglom/connectionpool_backends/postgres_self.h>
+#include <libglom/init.h>
+#include <libglom/privs.h>
+#include <libglom/db_utils.h>
+#include <libglom/utils.h>
+#include <giomm/file.h>
+#include <iostream>
+
+#include <glibmm/i18n.h>
+
+class GlomCreateOptionGroup : public Glib::OptionGroup
+{
+public:
+ GlomCreateOptionGroup();
+
+ //These instances should live as long as the OptionGroup to which they are added,
+ //and as long as the OptionContext to which those OptionGroups are added.
+ std::string m_arg_filename_input;
+ std::string m_arg_filepath_dir_output;
+ std::string m_arg_filepath_name_output;
+ bool m_arg_version;
+};
+
+GlomCreateOptionGroup::GlomCreateOptionGroup()
+: Glib::OptionGroup("glom_create_from_example", _("Glom options"), _("Command-line options")),
+ m_arg_version(false)
+{
+ Glib::OptionEntry entry;
+ entry.set_long_name("input");
+ entry.set_short_name('i');
+ entry.set_description(_("The example .glom file to open."));
+ add_entry_filename(entry, m_arg_filename_input);
+
+ Glib::OptionEntry entry2;
+ entry2.set_long_name("output-path");
+ entry2.set_short_name('o');
+ entry2.set_description(_("The directory in which to save the created .glom file, or sub-directory if necessary, such as /home/someuser/"));
+ add_entry_filename(entry2, m_arg_filepath_dir_output);
+
+ Glib::OptionEntry entry3;
+ entry3.set_long_name("output-name");
+ entry3.set_short_name('n');
+ entry3.set_description(_("The name for the created .glom file, such as something.glom"));
+ add_entry_filename(entry3, m_arg_filepath_name_output);
+
+ Glib::OptionEntry entry_version;
+ entry_version.set_long_name("version");
+ entry_version.set_short_name('V');
+ entry_version.set_description(_("The version of this application."));
+ add_entry(entry_version, m_arg_version);
+}
+
+static void on_initialize_progress()
+{
+ std::cout << "Database initialization progress" << std::endl;
+}
+
+static void on_startup_progress()
+{
+ std::cout << "Database startup progress" << std::endl;
+}
+
+static void on_recreate_progress()
+{
+ std::cout << "Database re-creation progress" << std::endl;
+}
+
+static void on_cleanup_progress()
+{
+ std::cout << "Database cleanup progress" << std::endl;
+}
+
+/** Delete a directory, if it exists, and its contents.
+ * Unlike g_file_delete(), this does not fail if the directory is not empty.
+ */
+static bool delete_directory(const Glib::RefPtr<Gio::File>& directory)
+{
+ if(!(directory->query_exists()))
+ return true;
+
+ //(Recursively) Delete any child files and directories,
+ //so we can delete this directory.
+ Glib::RefPtr<Gio::FileEnumerator> enumerator = directory->enumerate_children();
+
+ Glib::RefPtr<Gio::FileInfo> info = enumerator->next_file();
+ while(info)
+ {
+ Glib::RefPtr<Gio::File> child = directory->get_child(info->get_name());
+ bool removed_child = false;
+ if(child->query_file_type() == Gio::FILE_TYPE_DIRECTORY)
+ removed_child = delete_directory(child);
+ else
+ removed_child = child->remove();
+
+ if(!removed_child)
+ return false;
+
+ info = enumerator->next_file();
+ }
+
+ //Delete the actual directory:
+ if(!directory->remove())
+ return false;
+
+ return true;
+}
+
+/** Delete a directory, if it exists, and its contents.
+ * Unlike g_file_delete(), this does not fail if the directory is not empty.
+ */
+static bool delete_directory(const std::string& uri)
+{
+ if(uri.empty())
+ return true;
+
+ Glib::RefPtr<Gio::File> file = Gio::File::create_for_uri(uri);
+ return delete_directory(file);
+}
+
+std::string filepath_dir;
+
+static Glib::ustring convert_filepath_to_uri(const std::string& filepath)
+{
+ try
+ {
+ return Glib::filename_to_uri(filepath);
+ }
+ catch(const Glib::ConvertError& ex)
+ {
+ std::cerr << G_STRFUNC << ": Could not convert filepath to URI: " << filepath << std::endl;
+ return Glib::ustring();
+ }
+}
+
+static void cleanup()
+{
+ Glom::ConnectionPool* connection_pool = Glom::ConnectionPool::get_instance();
+
+ const bool stopped = connection_pool->cleanup( sigc::ptr_fun(&on_cleanup_progress) );
+ g_assert(stopped);
+
+ //Make sure the directory is removed at the end,
+ {
+ const Glib::ustring uri = convert_filepath_to_uri(filepath_dir);
+ delete_directory(uri);
+ }
+}
+
+
+int main(int argc, char* argv[])
+{
+ Glom::libglom_init();
+
+ Glib::OptionContext context;
+ GlomCreateOptionGroup group;
+ context.set_main_group(group);
+
+ try
+ {
+ context.parse(argc, argv);
+ }
+ catch(const Glib::OptionError& ex)
+ {
+ std::cout << _("Error while parsing command-line options: ") << std::endl << ex.what() << std::endl;
+ std::cout << _("Use --help to see a list of available command-line options.") << std::endl;
+ return 0;
+ }
+ catch(const Glib::Error& ex)
+ {
+ std::cout << "Error: " << ex.what() << std::endl;
+ return 0;
+ }
+
+ if(group.m_arg_version)
+ {
+ std::cout << PACKAGE_STRING << std::endl;
+ return 0;
+ }
+
+ // Get a URI for a test file:
+ Glib::ustring input_uri = group.m_arg_filename_input;
+
+ // The GOption documentation says that options without names will be returned to the application as "rest arguments".
+ // I guess this means they will be left in the argv. Murray.
+ if(input_uri.empty() && (argc > 1))
+ {
+ const char* pch = argv[1];
+ if(pch)
+ input_uri = pch;
+ }
+
+ if(!input_uri.empty())
+ {
+ //Get a URI (file://something) from the filepath:
+ Glib::RefPtr<Gio::File> file = Gio::File::create_for_commandline_arg(input_uri);
+
+ if(!file->query_exists())
+ {
+ std::cerr << _("Glom: The file does not exist.") << std::endl;
+ std::cerr << "uri: " << input_uri << std::endl;
+
+ std::cerr << std::endl << context.get_help() << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ const Gio::FileType file_type = file->query_file_type();
+ if(file_type == Gio::FILE_TYPE_DIRECTORY)
+ {
+ std::cerr << _("Glom: The file path is a directory instead of a file.") << std::endl;
+ std::cerr << std::endl << context.get_help() << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ input_uri = file->get_uri();
+
+ }
+
+ if(input_uri.empty())
+ {
+ std::cerr << "Please specify a glom example file." << std::endl;
+ std::cerr << std::endl << context.get_help() << std::endl;
+ return EXIT_FAILURE;
+ }
+
+
+ //Check the output directory path:
+ if(group.m_arg_filepath_dir_output.empty())
+ {
+ std::cerr << "Please specify an output directory path." << std::endl;
+ std::cerr << std::endl << context.get_help() << std::endl;
+ return EXIT_FAILURE;
+ }
+ else
+ {
+ //Get a URI (file://something) from the filepath:
+ Glib::RefPtr<Gio::File> file = Gio::File::create_for_commandline_arg(group.m_arg_filepath_dir_output);
+
+ if(!file->query_exists())
+ {
+ std::cerr << _("Glom: The output directory does not exist.") << std::endl;
+ std::cerr << "uri: " << group.m_arg_filepath_dir_output << std::endl;
+
+ std::cerr << std::endl << context.get_help() << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ const Gio::FileType file_type = file->query_file_type();
+ if(file_type != Gio::FILE_TYPE_DIRECTORY)
+ {
+ std::cerr << _("Glom: The output path is not a directory.") << std::endl;
+ std::cerr << std::endl << context.get_help() << std::endl;
+ return EXIT_FAILURE;
+ }
+ }
+
+ //Check the output name path:
+ if(group.m_arg_filepath_name_output.empty())
+ {
+ std::cerr << "Please specify an output name." << std::endl;
+ std::cerr << std::endl << context.get_help() << std::endl;
+ return EXIT_FAILURE;
+ }
+
+
+ // Load the document:
+ Glom::Document document;
+ document.set_file_uri(input_uri);
+ int failure_code = 0;
+ const bool test = document.load(failure_code);
+ //std::cout << "Document load result=" << test << std::endl;
+
+ if(!test)
+ {
+ std::cerr << "Document::load() failed with failure_code=" << failure_code << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ g_assert(document.get_is_example_file());;
+
+ Glom::ConnectionPool* connection_pool = Glom::ConnectionPool::get_instance();
+
+ //Save a copy, specifying the path to file in a directory:
+ filepath_dir =
+ Glom::Utils::get_file_path_without_extension(
+ Glib::build_filename(
+ group.m_arg_filepath_dir_output,
+ group.m_arg_filepath_name_output));
+ const std::string filepath =
+ Glib::build_filename(filepath_dir, group.m_arg_filepath_name_output);
+
+ //Make sure that the file does not exist yet:
+ {
+ const Glib::ustring uri = convert_filepath_to_uri(filepath_dir);
+ if(uri.empty())
+ return EXIT_FAILURE;
+
+ Glib::RefPtr<Gio::File> file = Gio::File::create_for_commandline_arg(uri);
+ if(file->query_exists())
+ {
+ std::cerr << "The output path already exists: " << filepath_dir << std::endl;
+ return EXIT_FAILURE;
+ }
+ }
+
+ //Save the example as a real file:
+ const Glib::ustring file_uri = convert_filepath_to_uri(filepath);
+ if(file_uri.empty())
+ return EXIT_FAILURE;
+
+ document.set_file_uri(file_uri);
+
+ document.set_hosting_mode(Glom::Document::HOSTING_MODE_POSTGRES_SELF);
+ document.set_is_example_file(false);
+ document.set_network_shared(false);
+ const bool saved = document.save();
+ g_assert(saved);
+
+ //Specify the backend and backend-specific details to be used by the connectionpool.
+ connection_pool->setup_from_document(&document);
+
+ //We must specify a default username and password:
+ Glib::ustring password;
+ const Glib::ustring user = Glom::Privs::get_default_developer_user_name(password);
+ connection_pool->set_user(user);
+ connection_pool->set_password(password);
+
+ //Create the self-hosting files:
+ const Glom::ConnectionPool::InitErrors initialized_errors =
+ connection_pool->initialize( sigc::ptr_fun(&on_initialize_progress) );
+ g_assert(initialized_errors == Glom::ConnectionPool::Backend::INITERROR_NONE);
+
+ //Start self-hosting:
+ //TODO: Let this happen automatically on first connection?
+ const Glom::ConnectionPool::StartupErrors started = connection_pool->startup( sigc::ptr_fun(&on_startup_progress) );
+ if(started != Glom::ConnectionPool::Backend::STARTUPERROR_NONE)
+ {
+ std::cerr << "connection_pool->startup(): result=" << started << std::endl;
+ cleanup();
+ }
+ g_assert(started == Glom::ConnectionPool::Backend::STARTUPERROR_NONE);
+
+ const bool recreated = Glom::DbUtils::recreate_database_from_document(&document, sigc::ptr_fun(&on_recreate_progress) );
+ if(!recreated)
+ cleanup();
+ g_assert(recreated);
+
+
+ //Tell the user where the file is:
+ std::string output_path_used;
+ try
+ {
+ output_path_used = Glib::filename_from_uri(document.get_file_uri());
+ }
+ catch(const Glib::ConvertError& ex)
+ {
+ std::cerr << G_STRFUNC << ": Could not convert URI to output filepath: " << document.get_file_uri() << std::endl;
+ }
+
+ std::cout << "Glom file created at: " << output_path_used << std::endl;
+
+
+ Glom::libglom_deinit();
+
+ return EXIT_SUCCESS;
+}
diff --git a/glom/main.cc b/glom/main.cc
index a356193..4f8a727 100644
--- a/glom/main.cc
+++ b/glom/main.cc
@@ -48,7 +48,6 @@
#include <gtksourceviewmm/init.h>
#include <goocanvasmm/init.h>
#endif // !GLOM_ENABLE_CLIENT_ONLY
-#include <glibmm/i18n.h>
#include <glom/application.h>
#include <glom/glade_utils.h>
@@ -56,6 +55,8 @@
#include <evince-view.h>
+#include <glibmm/i18n.h>
+
#ifdef G_OS_WIN32
#include <winsock2.h>
#else
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]