diff --git a/src/lay/lay/laySaltGrainDetailsTextWidget.cc b/src/lay/lay/laySaltGrainDetailsTextWidget.cc
index 1992b20c9e..28eb81c6a9 100644
--- a/src/lay/lay/laySaltGrainDetailsTextWidget.cc
+++ b/src/lay/lay/laySaltGrainDetailsTextWidget.cc
@@ -305,7 +305,6 @@ SaltGrainDetailsTextWidget::details_text ()
if (! d->url.empty ()) {
stream << " - ";
stream << "[" << tl::to_qstring (tl::escaped_to_html (d->url)) << "]
";
- // @@@ TODO: protocol and branch
}
}
stream << "
";
diff --git a/src/lay/lay/laySaltGrainPropertiesDialog.cc b/src/lay/lay/laySaltGrainPropertiesDialog.cc
index 22ad35005a..061eee1ca2 100644
--- a/src/lay/lay/laySaltGrainPropertiesDialog.cc
+++ b/src/lay/lay/laySaltGrainPropertiesDialog.cc
@@ -187,7 +187,6 @@ SaltGrainPropertiesDialog::update_controls ()
dependency_changed (item, 0);
item->setData (1, Qt::UserRole, tl::to_qstring (d->version));
dependency_changed (item, 1);
- // @@@ TODO: protocol and branch?
item->setData (2, Qt::UserRole, tl::to_qstring (d->url));
dependency_changed (item, 2);
@@ -254,7 +253,6 @@ SaltGrainPropertiesDialog::update_data ()
dep.name = tl::to_string (name);
dep.version = tl::to_string (version);
dep.url = tl::to_string (url);
- // @@@ TODO: set protocol and branch
m_grain.dependencies ().push_back (dep);
}
diff --git a/src/tl/tl/tlFileUtils.cc b/src/tl/tl/tlFileUtils.cc
index 747d21c6fe..752c4085ce 100644
--- a/src/tl/tl/tlFileUtils.cc
+++ b/src/tl/tl/tlFileUtils.cc
@@ -27,6 +27,7 @@
#include "tlEnv.h"
#include
+#include
// Use this define to print debug output
// #define FILE_UTILS_VERBOSE
@@ -1018,4 +1019,108 @@ get_module_path (void *addr)
#endif
}
+std::string
+tmpfile (const std::string &domain)
+{
+ std::string tmp = tl::get_env ("TMPDIR");
+ if (tmp.empty ()) {
+ tmp = tl::get_env ("TMP");
+ }
+ if (tmp.empty ()) {
+#if defined(_WIN32)
+ throw tl::Exception (tl::to_string (tr ("TMP and TMPDIR not set - cannot create temporary file")));
+#else
+ tmp = "/tmp";
+#endif
+ }
+
+ std::string templ = tl::combine_path (tmp, domain + "XXXXXX");
+ char *tmpstr = strdup (templ.c_str ());
+
+#if defined(_WIN32)
+ if (_mktemp_s (tmpstr, templ) != 0) {
+ free (tmpstr);
+ throw tl::Exception (tl::to_string (tr ("Unable to create temporary folder name in %s")), tmp);
+ }
+
+ // for compatibility with Linux, create the file as an empty one
+ std::ofstream os (tmpstr);
+ if (os.bad ()) {
+ throw tl::Exception (tl::to_string (tr ("Unable to create temporary folder in %s")), tmp);
+ }
+ os.close ();
+#else
+ int fd = mkstemp (tmpstr);
+ if (fd < 0) {
+ free (tmpstr);
+ throw tl::Exception (tl::to_string (tr ("Unable to create temporary folder in %s")), tmp);
+ }
+ close (fd);
+#endif
+
+ std::string res = tmpstr;
+ free (tmpstr);
+ return res;
+}
+
+TemporaryFile::TemporaryFile (const std::string &domain)
+{
+ m_path = tmpfile (domain);
+}
+
+TemporaryFile::~TemporaryFile ()
+{
+ tl::rm_file (m_path);
+}
+
+std::string
+tmpdir (const std::string &domain)
+{
+ std::string tmp = tl::get_env ("TMPDIR");
+ if (tmp.empty ()) {
+ tmp = tl::get_env ("TMP");
+ }
+ if (tmp.empty ()) {
+#if defined(_WIN32)
+ throw tl::Exception (tl::to_string (tr ("TMP and TMPDIR not set - cannot create temporary file")));
+#else
+ tmp = "/tmp";
+#endif
+ }
+
+ std::string templ = tl::combine_path (tmp, domain + "XXXXXX");
+ char *tmpstr = strdup (templ.c_str ());
+
+#if defined(_WIN32)
+ if (_mktemp_s (tmpstr, templ) != 0) {
+ free (tmpstr);
+ throw tl::Exception (tl::to_string (tr ("Unable to create temporary folder name in %s")), tmp);
+ }
+ if (! tl::mkdir (tmpstr)) {
+ free (tmpstr);
+ throw tl::Exception (tl::to_string (tr ("Unable to create temporary folder in %s")), tmp);
+ }
+#else
+ if (mkdtemp (tmpstr) == NULL) {
+ free (tmpstr);
+ throw tl::Exception (tl::to_string (tr ("Unable to create temporary folder in %s")), tmp);
+ }
+#endif
+
+ std::string res = tmpstr;
+ free (tmpstr);
+ return res;
+}
+
+TemporaryDirectory::TemporaryDirectory (const std::string &domain)
+{
+ m_path = tmpdir (domain);
+}
+
+TemporaryDirectory::~TemporaryDirectory ()
+{
+ tl::rm_dir_recursive (m_path);
+}
+
+
}
diff --git a/src/tl/tl/tlFileUtils.h b/src/tl/tl/tlFileUtils.h
index 0649b4078c..474ec7e29d 100644
--- a/src/tl/tl/tlFileUtils.h
+++ b/src/tl/tl/tlFileUtils.h
@@ -188,6 +188,68 @@ std::string TL_PUBLIC current_dir ();
*/
bool TL_PUBLIC chdir (const std::string &path);
+/**
+ * @brief Gets a temporary file path
+ *
+ * This function will make a temporary file with a unique name.
+ * The "domain" string is used as part of the file name as an disambiguator.
+ *
+ * The function reads $TMPDIR or $TMP to define the location of the temporary
+ * directory. On Linux, the default is /tmp.
+ *
+ * The file is created and it is the responsibility of the caller to remove
+ * the file.
+ */
+std::string TL_PUBLIC tmpfile (const std::string &domain = std::string ());
+
+/**
+ * @brief A class wrapping a temporary file
+ *
+ * In the destructor of this class, the temporary file will be deleted again.
+ */
+class TL_PUBLIC TemporaryFile
+{
+public:
+ TemporaryFile (const std::string &domain = std::string ());
+ ~TemporaryFile ();
+
+ const std::string &path () const
+ {
+ return m_path;
+ }
+
+private:
+ std::string m_path;
+};
+
+/**
+ * @brief Gets a temporary folder path
+ *
+ * Similar to "tmpfile", but will create a new, empty folder. Again it is the
+ * reposibility of the caller to clean up.
+ */
+std::string TL_PUBLIC tmpdir (const std::string &domain = std::string ());
+
+/**
+ * @brief A class wrapping a temporary directory
+ *
+ * In the destructor of this class, the temporary directory will be deleted again.
+ */
+class TL_PUBLIC TemporaryDirectory
+{
+public:
+ TemporaryDirectory (const std::string &domain = std::string ());
+ ~TemporaryDirectory ();
+
+ const std::string &path () const
+ {
+ return m_path;
+ }
+
+private:
+ std::string m_path;
+};
+
/**
* @brief This function splits the path into it's components
* On Windows, the first component may be the drive prefix ("C:") or
diff --git a/src/tl/tl/tlGit.cc b/src/tl/tl/tlGit.cc
index 95470580f3..12298d93fc 100644
--- a/src/tl/tl/tlGit.cc
+++ b/src/tl/tl/tlGit.cc
@@ -78,12 +78,7 @@ GitObject::GitObject (const std::string &local_path)
InitHelper::ensure_initialized ();
if (local_path.empty ()) {
- // @@@ generic tempnam on Windows/Posix ...
- char tmp[] = "/tmp/git2klayoutXXXXXX";
- if (mkdtemp (tmp) == NULL) {
- throw tl::Exception (tl::to_string (tr ("Unable to create temporary folder: %s")), (const char *) tmp);
- }
- m_local_path = tmp;
+ m_local_path = tl::tmpdir ("git2klayout");
m_is_temp = true;
}
diff --git a/src/tl/unit_tests/tlFileUtilsTests.cc b/src/tl/unit_tests/tlFileUtilsTests.cc
index 4814901c2e..768b0943a5 100644
--- a/src/tl/unit_tests/tlFileUtilsTests.cc
+++ b/src/tl/unit_tests/tlFileUtilsTests.cc
@@ -875,3 +875,83 @@ TEST (20)
EXPECT_EQ (tl::absolute_file_path ("~"), tl::get_home_path ());
EXPECT_EQ (tl::absolute_file_path (tl::combine_path ("~", "test")), tl::combine_path (tl::get_home_path (), "test"));
}
+
+// tmpfile
+TEST (21)
+{
+ std::string p = tl::tmpfile ("tl_tests");
+ EXPECT_EQ (tl::file_exists (p), true);
+
+ std::ofstream os (p);
+ os << "A test";
+ os.close ();
+
+ tl::InputStream is (p);
+ EXPECT_EQ (is.read_all (), "A test");
+
+ EXPECT_EQ (tl::rm_file (p), true);
+ EXPECT_EQ (tl::file_exists (p), false);
+}
+
+// TemporaryFile
+TEST (22)
+{
+ std::string p;
+
+ {
+ tl::TemporaryFile tf ("tl_tests");
+ p = tf.path ();
+ EXPECT_EQ (tl::file_exists (tf.path ()), true);
+
+ std::ofstream os (tf.path ());
+ os << "A test";
+ os.close ();
+
+ tl::InputStream is (tf.path ());
+ EXPECT_EQ (is.read_all (), "A test");
+ }
+
+ EXPECT_EQ (tl::file_exists (p), false);
+}
+
+// tmpdir
+TEST (23)
+{
+ std::string p = tl::tmpdir ("tl_tests");
+ EXPECT_EQ (tl::file_exists (p), true);
+ EXPECT_EQ (tl::is_dir (p), true);
+
+ std::ofstream os (tl::combine_path (p, "test"));
+ os << "A test";
+ os.close ();
+
+ tl::InputStream is (tl::combine_path (p, "test"));
+ EXPECT_EQ (is.read_all (), "A test");
+
+ EXPECT_EQ (tl::rm_dir_recursive (p), true);
+ EXPECT_EQ (tl::file_exists (p), false);
+}
+
+// TemporaryDirectory object
+TEST (24)
+{
+ std::string p;
+
+ {
+ tl::TemporaryDirectory tmpdir ("tl_tests");
+ p = tmpdir.path ();
+
+ EXPECT_EQ (tl::file_exists (p), true);
+ EXPECT_EQ (tl::is_dir (p), true);
+
+ std::ofstream os (tl::combine_path (p, "test"));
+ os << "A test";
+ os.close ();
+
+ tl::InputStream is (tl::combine_path (p, "test"));
+ EXPECT_EQ (is.read_all (), "A test");
+ }
+
+ EXPECT_EQ (tl::file_exists (p), false);
+}
+