mirror of
https://github.com/ostreedev/ostree.git
synced 2025-01-11 09:18:20 +03:00
commit: Support reading current directory rather than requiring 'find'
Implement 'find' internally.
This commit is contained in:
parent
5cfc66496c
commit
b15eee447a
@ -24,6 +24,8 @@
|
|||||||
#include "ot-builtins.h"
|
#include "ot-builtins.h"
|
||||||
#include "ostree.h"
|
#include "ostree.h"
|
||||||
|
|
||||||
|
#include <gio/gunixoutputstream.h>
|
||||||
|
|
||||||
#include <glib/gi18n.h>
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
static gboolean separator_null;
|
static gboolean separator_null;
|
||||||
@ -51,28 +53,176 @@ static GOptionEntry options[] = {
|
|||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GFile *dir;
|
||||||
|
char separator;
|
||||||
|
GOutputStream *out;
|
||||||
|
GCancellable *cancellable;
|
||||||
|
} FindThreadData;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
find (const char *basepath,
|
||||||
|
GFile *dir,
|
||||||
|
char separator,
|
||||||
|
GOutputStream *out,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
find_write_child (const char *basepath,
|
||||||
|
GFile *dir,
|
||||||
|
char separator,
|
||||||
|
GOutputStream *out,
|
||||||
|
GFileInfo *finfo,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
guint32 type;
|
||||||
|
const char *name;
|
||||||
|
char buf[1];
|
||||||
|
char *child_path = NULL;
|
||||||
|
GString *child_trimmed_path = NULL;
|
||||||
|
GFile *child = NULL;
|
||||||
|
gsize bytes_written;
|
||||||
|
|
||||||
|
type = g_file_info_get_attribute_uint32 (finfo, "standard::type");
|
||||||
|
name = g_file_info_get_attribute_byte_string (finfo, "standard::name");
|
||||||
|
|
||||||
|
child = g_file_get_child (dir, name);
|
||||||
|
|
||||||
|
if (type == G_FILE_TYPE_DIRECTORY)
|
||||||
|
{
|
||||||
|
if (!find (basepath, child, separator, out, cancellable, error))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
child_path = g_file_get_path (child);
|
||||||
|
child_trimmed_path = g_string_new (child_path + strlen (basepath));
|
||||||
|
if (!*(child_trimmed_path->str))
|
||||||
|
{
|
||||||
|
/* do nothing - we implicitly add the root . */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_assert (*(child_trimmed_path->str) == '/');
|
||||||
|
g_string_insert_c (child_trimmed_path, 0, '.');
|
||||||
|
|
||||||
|
if (!g_output_stream_write_all (out, child_trimmed_path->str, child_trimmed_path->len,
|
||||||
|
&bytes_written, cancellable, error))
|
||||||
|
goto out;
|
||||||
|
buf[0] = separator;
|
||||||
|
if (!g_output_stream_write_all (out, buf, 1, &bytes_written,
|
||||||
|
cancellable, error))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
out:
|
||||||
|
g_string_free (child_trimmed_path, TRUE);
|
||||||
|
child_trimmed_path = NULL;
|
||||||
|
g_free (child_path);
|
||||||
|
child_path = NULL;
|
||||||
|
g_clear_object (&child);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
find (const char *basepath,
|
||||||
|
GFile *dir,
|
||||||
|
char separator,
|
||||||
|
GOutputStream *out,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
GError *temp_error = NULL;
|
||||||
|
GFileEnumerator *enumerator = NULL;
|
||||||
|
GFileInfo *finfo = NULL;
|
||||||
|
|
||||||
|
enumerator = g_file_enumerate_children (dir, "standard::type,standard::name",
|
||||||
|
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||||
|
cancellable, error);
|
||||||
|
if (!enumerator)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
while ((finfo = g_file_enumerator_next_file (enumerator, cancellable, error)) != NULL)
|
||||||
|
{
|
||||||
|
if (!find_write_child (basepath, dir, separator, out, finfo, cancellable, error))
|
||||||
|
goto out;
|
||||||
|
g_clear_object (&finfo);
|
||||||
|
}
|
||||||
|
if (temp_error)
|
||||||
|
{
|
||||||
|
g_propagate_error (error, temp_error);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
out:
|
||||||
|
g_clear_object (&finfo);
|
||||||
|
g_clear_object (&enumerator);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gpointer
|
||||||
|
find_thread (gpointer data)
|
||||||
|
{
|
||||||
|
FindThreadData *tdata = data;
|
||||||
|
GError *error = NULL;
|
||||||
|
char *path;
|
||||||
|
|
||||||
|
path = g_file_get_path (tdata->dir);
|
||||||
|
if (!find (path, tdata->dir, tdata->separator, tdata->out,
|
||||||
|
tdata->cancellable, &error))
|
||||||
|
{
|
||||||
|
g_printerr ("%s", error->message);
|
||||||
|
g_clear_error (&error);
|
||||||
|
}
|
||||||
|
g_free (path);
|
||||||
|
g_clear_object (&(tdata->dir));
|
||||||
|
g_clear_object (&(tdata->out));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
ostree_builtin_commit (int argc, char **argv, const char *repo_path, GError **error)
|
ostree_builtin_commit (int argc, char **argv, const char *repo_path, GError **error)
|
||||||
{
|
{
|
||||||
GOptionContext *context;
|
GOptionContext *context;
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
OstreeRepo *repo = NULL;
|
OstreeRepo *repo = NULL;
|
||||||
char *cwd;
|
char *dir;
|
||||||
gboolean using_filename_cmdline;
|
gboolean using_filename_cmdline;
|
||||||
gboolean using_filedescriptors;
|
gboolean using_filedescriptors;
|
||||||
GPtrArray *additions_array = NULL;
|
GPtrArray *additions_array = NULL;
|
||||||
GPtrArray *removals_array = NULL;
|
GPtrArray *removals_array = NULL;
|
||||||
GChecksum *commit_checksum = NULL;
|
GChecksum *commit_checksum = NULL;
|
||||||
char **iter;
|
char **iter;
|
||||||
|
char separator;
|
||||||
|
|
||||||
cwd = g_get_current_dir ();
|
context = g_option_context_new ("[DIR] - Commit a new revision");
|
||||||
|
|
||||||
context = g_option_context_new ("- Commit a new revision");
|
|
||||||
g_option_context_add_main_entries (context, options, NULL);
|
g_option_context_add_main_entries (context, options, NULL);
|
||||||
|
|
||||||
if (!g_option_context_parse (context, &argc, &argv, error))
|
if (!g_option_context_parse (context, &argc, &argv, error))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
if (argc > 1)
|
||||||
|
dir = g_strdup (argv[1]);
|
||||||
|
else
|
||||||
|
dir = g_get_current_dir ();
|
||||||
|
|
||||||
|
if (g_str_has_suffix (dir, "/"))
|
||||||
|
dir[strlen (dir) - 1] = '\0';
|
||||||
|
|
||||||
|
separator = separator_null ? '\0' : '\n';
|
||||||
|
|
||||||
|
if (!*dir)
|
||||||
|
{
|
||||||
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
"Invalid empty directory");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
repo = ostree_repo_new (repo_path);
|
repo = ostree_repo_new (repo_path);
|
||||||
if (!ostree_repo_check (repo, error))
|
if (!ostree_repo_check (repo, error))
|
||||||
goto out;
|
goto out;
|
||||||
@ -80,12 +230,6 @@ ostree_builtin_commit (int argc, char **argv, const char *repo_path, GError **er
|
|||||||
using_filename_cmdline = (removals || additions);
|
using_filename_cmdline = (removals || additions);
|
||||||
using_filedescriptors = (from_file || from_fd >= 0 || from_stdin);
|
using_filedescriptors = (from_file || from_fd >= 0 || from_stdin);
|
||||||
|
|
||||||
if (!(using_filename_cmdline || using_filedescriptors))
|
|
||||||
{
|
|
||||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
||||||
"No additions or removals specified");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (using_filename_cmdline && using_filedescriptors)
|
if (using_filename_cmdline && using_filedescriptors)
|
||||||
{
|
{
|
||||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
@ -121,7 +265,7 @@ ostree_builtin_commit (int argc, char **argv, const char *repo_path, GError **er
|
|||||||
g_ptr_array_add (removals_array, *iter);
|
g_ptr_array_add (removals_array, *iter);
|
||||||
|
|
||||||
if (!ostree_repo_commit (repo, branch, parent, subject, body, NULL,
|
if (!ostree_repo_commit (repo, branch, parent, subject, body, NULL,
|
||||||
cwd, additions_array,
|
dir, additions_array,
|
||||||
removals_array,
|
removals_array,
|
||||||
&commit_checksum,
|
&commit_checksum,
|
||||||
error))
|
error))
|
||||||
@ -129,7 +273,6 @@ ostree_builtin_commit (int argc, char **argv, const char *repo_path, GError **er
|
|||||||
}
|
}
|
||||||
else if (using_filedescriptors)
|
else if (using_filedescriptors)
|
||||||
{
|
{
|
||||||
char separator = separator_null ? '\0' : '\n';
|
|
||||||
gboolean temp_fd = -1;
|
gboolean temp_fd = -1;
|
||||||
|
|
||||||
if (from_stdin)
|
if (from_stdin)
|
||||||
@ -145,7 +288,7 @@ ostree_builtin_commit (int argc, char **argv, const char *repo_path, GError **er
|
|||||||
from_fd = temp_fd;
|
from_fd = temp_fd;
|
||||||
}
|
}
|
||||||
if (!ostree_repo_commit_from_filelist_fd (repo, branch, parent, subject, body, NULL,
|
if (!ostree_repo_commit_from_filelist_fd (repo, branch, parent, subject, body, NULL,
|
||||||
cwd, from_fd, separator,
|
dir, from_fd, separator,
|
||||||
&commit_checksum, error))
|
&commit_checksum, error))
|
||||||
{
|
{
|
||||||
if (temp_fd >= 0)
|
if (temp_fd >= 0)
|
||||||
@ -155,11 +298,40 @@ ostree_builtin_commit (int argc, char **argv, const char *repo_path, GError **er
|
|||||||
if (temp_fd >= 0)
|
if (temp_fd >= 0)
|
||||||
close (temp_fd);
|
close (temp_fd);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int pipefd[2];
|
||||||
|
GOutputStream *out;
|
||||||
|
FindThreadData fdata;
|
||||||
|
|
||||||
|
if (pipe (pipefd) < 0)
|
||||||
|
{
|
||||||
|
ot_util_set_error_from_errno (error, errno);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out = (GOutputStream*)g_unix_output_stream_new (pipefd[1], TRUE);
|
||||||
|
|
||||||
|
fdata.dir = ot_util_new_file_for_path (dir);
|
||||||
|
fdata.separator = separator;
|
||||||
|
fdata.out = out;
|
||||||
|
fdata.cancellable = NULL;
|
||||||
|
|
||||||
|
if (g_thread_create (find_thread, &fdata, FALSE, error) == NULL)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!ostree_repo_commit_from_filelist_fd (repo, branch, parent, subject, body, NULL,
|
||||||
|
dir, pipefd[0], separator,
|
||||||
|
&commit_checksum, error))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
(void)close (pipefd[0]);
|
||||||
|
}
|
||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
g_print ("%s\n", g_checksum_get_string (commit_checksum));
|
g_print ("%s\n", g_checksum_get_string (commit_checksum));
|
||||||
out:
|
out:
|
||||||
g_free (cwd);
|
g_free (dir);
|
||||||
if (context)
|
if (context)
|
||||||
g_option_context_free (context);
|
g_option_context_free (context);
|
||||||
g_clear_object (&repo);
|
g_clear_object (&repo);
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
echo "1..8"
|
echo "1..10"
|
||||||
|
|
||||||
. libtest.sh
|
. libtest.sh
|
||||||
|
|
||||||
@ -77,3 +77,19 @@ cd checkout-test2-3
|
|||||||
assert_has_file a/nested/2
|
assert_has_file a/nested/2
|
||||||
assert_file_has_content a/nested/2 'two2'
|
assert_file_has_content a/nested/2 'two2'
|
||||||
echo "ok stdin contents"
|
echo "ok stdin contents"
|
||||||
|
|
||||||
|
cd ${test_tmpdir}/checkout-test2-3
|
||||||
|
echo 4 > four
|
||||||
|
mkdir -p yet/another/tree
|
||||||
|
echo leaf > yet/another/tree/green
|
||||||
|
echo helloworld > yet/message
|
||||||
|
$OSTREE commit -b test2 -s "Current directory"
|
||||||
|
echo "ok cwd commit"
|
||||||
|
|
||||||
|
cd ${test_tmpdir}
|
||||||
|
$OSTREE checkout test2 $test_tmpdir/checkout-test2-4
|
||||||
|
cd checkout-test2-4
|
||||||
|
assert_file_has_content yet/another/tree/green 'leaf'
|
||||||
|
assert_file_has_content four '4'
|
||||||
|
echo "ok cwd contents"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user