[hacktree] Don't include any timestamps in hash, add fsck command
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [hacktree] Don't include any timestamps in hash, add fsck command
- Date: Wed, 12 Oct 2011 17:45:55 +0000 (UTC)
commit cd3a56dd68d8caf365236f23c2f52cc709baae2b
Author: Colin Walters <walters verbum org>
Date: Wed Oct 12 11:38:41 2011 -0400
Don't include any timestamps in hash, add fsck command
Makefile-hacktree.am | 3 +
src/ht-builtin-fsck.c | 114 ++++++++++++++++
src/ht-builtins.h | 1 +
src/libhacktree/hacktree-core.c | 203 +++++++++++++++++++++++++++
src/libhacktree/hacktree-core.h | 36 +++++
src/libhacktree/hacktree-repo.c | 287 ++++++++++++++++-----------------------
src/libhacktree/hacktree-repo.h | 8 +
src/libhacktree/hacktree.h | 1 +
src/libhtutil/ht-unix-utils.c | 1 -
src/main.c | 1 +
10 files changed, 483 insertions(+), 172 deletions(-)
---
diff --git a/Makefile-hacktree.am b/Makefile-hacktree.am
index 308f3c0..77bf547 100644
--- a/Makefile-hacktree.am
+++ b/Makefile-hacktree.am
@@ -13,6 +13,8 @@ libhtutil_la_LIBADD = $(GIO_UNIX_LIBS)
noinst_LTLIBRARIES += libhacktree.la
libhacktree_la_SOURCES = src/libhacktree/hacktree.h \
+ src/libhacktree/hacktree-core.c \
+ src/libhacktree/hacktree-core.h \
src/libhacktree/hacktree-repo.c \
src/libhacktree/hacktree-repo.h \
src/libhacktree/hacktree-types.h \
@@ -26,6 +28,7 @@ hacktree_SOURCES = src/main.c \
src/ht-builtins.h \
src/ht-builtin-init.c \
src/ht-builtin-link-file.c \
+ src/ht-builtin-fsck.c \
$(NULL)
hacktree_CFLAGS = -I$(srcdir)/src -I$(srcdir)/src/libhacktree -I$(srcdir)/src/libhtutil -DLOCALEDIR=\"$(datadir)/locale\" $(GIO_UNIX_CFLAGS)
hacktree_LDADD = libhtutil.la libhacktree.la $(GIO_UNIX_LIBS)
diff --git a/src/ht-builtin-fsck.c b/src/ht-builtin-fsck.c
new file mode 100644
index 0000000..61737c5
--- /dev/null
+++ b/src/ht-builtin-fsck.c
@@ -0,0 +1,114 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2011 Colin Walters <walters verbum org>
+ *
+ * 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 Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Colin Walters <walters verbum org>
+ */
+
+#include "config.h"
+
+#include "ht-builtins.h"
+#include "hacktree.h"
+
+#include <glib/gi18n.h>
+
+static char *repo_path;
+
+static GOptionEntry options[] = {
+ { "repo", 0, 0, G_OPTION_ARG_FILENAME, &repo_path, "Repository path", NULL },
+ { NULL }
+};
+
+typedef struct {
+ guint n_objects;
+} HtFsckData;
+
+static void
+object_iter_callback (HacktreeRepo *repo,
+ const char *path,
+ GFileInfo *file_info,
+ gpointer user_data)
+{
+ HtFsckData *data = user_data;
+ guint32 nlinks;
+ struct stat stbuf;
+ GChecksum *checksum = NULL;
+ GError *error = NULL;
+ char *dirname;
+ char *checksum_prefix;
+ char *checksum_string;
+
+ dirname = g_path_get_dirname (path);
+ checksum_prefix = g_path_get_basename (dirname);
+
+ nlinks = g_file_info_get_attribute_uint32 (file_info, "unix::nlink");
+
+ if (nlinks < 2)
+ g_printerr ("note: floating object: %s\n", path);
+
+ if (!hacktree_stat_and_checksum_file (-1, path, &checksum, &stbuf, &error))
+ goto out;
+
+ checksum_string = g_strconcat (checksum_prefix, g_file_info_get_name (file_info), NULL);
+
+ if (strcmp (checksum_string, g_checksum_get_string (checksum)) != 0)
+ {
+ g_printerr ("ERROR: corrupted object '%s' expected checksum: %s\n",
+ path, g_checksum_get_string (checksum));
+ }
+
+ data->n_objects++;
+
+ out:
+ if (checksum != NULL)
+ g_checksum_free (checksum);
+ g_free (dirname);
+ g_free (checksum_prefix);
+ if (error != NULL)
+ {
+ g_printerr ("%s\n", error->message);
+ g_clear_error (&error);
+ }
+}
+
+gboolean
+hacktree_builtin_fsck (int argc, const char **argv, const char *prefix, GError **error)
+{
+ HtFsckData data;
+ gboolean ret = FALSE;
+ HacktreeRepo *repo = NULL;
+ int i;
+
+ if (repo_path == NULL)
+ repo_path = ".";
+
+ data.n_objects = 0;
+
+ repo = hacktree_repo_new (repo_path);
+ if (!hacktree_repo_check (repo, error))
+ goto out;
+
+ if (!hacktree_repo_iter_objects (repo, object_iter_callback, &data, error))
+ goto out;
+
+ g_printerr ("Total Objects: %u\n", data.n_objects);
+
+ ret = TRUE;
+ out:
+ g_clear_object (&repo);
+ return ret;
+}
diff --git a/src/ht-builtins.h b/src/ht-builtins.h
index fee9777..58e6914 100644
--- a/src/ht-builtins.h
+++ b/src/ht-builtins.h
@@ -38,6 +38,7 @@ typedef struct {
gboolean hacktree_builtin_init (int argc, const char **argv, const char *prefix, GError **error);
gboolean hacktree_builtin_link_file (int argc, const char **argv, const char *prefix, GError **error);
+gboolean hacktree_builtin_fsck (int argc, const char **argv, const char *prefix, GError **error);
G_END_DECLS
diff --git a/src/libhacktree/hacktree-core.c b/src/libhacktree/hacktree-core.c
new file mode 100644
index 0000000..ddda1b5
--- /dev/null
+++ b/src/libhacktree/hacktree-core.c
@@ -0,0 +1,203 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2011 Colin Walters <walters verbum org>
+ *
+ * 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 Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Colin Walters <walters verbum org>
+ */
+
+#include "config.h"
+
+#include "hacktree.h"
+#include "htutil.h"
+
+char *
+stat_to_string (struct stat *stbuf)
+{
+ return g_strdup_printf ("%d:%d:%d", stbuf->st_mode, stbuf->st_uid, stbuf->st_gid);
+}
+
+static char *
+canonicalize_xattrs (char *xattr_string, size_t len)
+{
+ char *p;
+ GSList *xattrs = NULL;
+ GSList *iter;
+ GString *result;
+
+ result = g_string_new (0);
+
+ p = xattr_string;
+ while (p < xattr_string+len)
+ {
+ xattrs = g_slist_prepend (xattrs, p);
+ p += strlen (p) + 1;
+ }
+
+ xattrs = g_slist_sort (xattrs, (GCompareFunc) strcmp);
+ for (iter = xattrs; iter; iter = iter->next)
+ g_string_append (result, iter->data);
+
+ g_slist_free (xattrs);
+ return g_string_free (result, FALSE);
+}
+
+gboolean
+hacktree_stat_and_checksum_file (int dir_fd, const char *path,
+ GChecksum **out_checksum,
+ struct stat *out_stbuf,
+ GError **error)
+{
+ GChecksum *content_sha256 = NULL;
+ GChecksum *content_and_meta_sha256 = NULL;
+ char *stat_string = NULL;
+ ssize_t bytes_read;
+ char *xattrs = NULL;
+ char *xattrs_canonicalized = NULL;
+ int fd = -1;
+ DIR *temp_dir = NULL;
+ char *basename = NULL;
+ gboolean ret = FALSE;
+ char *symlink_target = NULL;
+ char *device_id = NULL;
+
+ basename = g_path_get_basename (path);
+
+ if (dir_fd == -1)
+ {
+ char *dirname = g_path_get_dirname (path);
+ temp_dir = opendir (dirname);
+ if (temp_dir == NULL)
+ {
+ ht_util_set_error_from_errno (error, errno);
+ g_free (dirname);
+ }
+ g_free (dirname);
+ dir_fd = dirfd (temp_dir);
+ }
+
+ if (fstatat (dir_fd, basename, out_stbuf, AT_SYMLINK_NOFOLLOW) < 0)
+ {
+ ht_util_set_error_from_errno (error, errno);
+ goto out;
+ }
+
+ if (!S_ISLNK(out_stbuf->st_mode))
+ {
+ fd = ht_util_open_file_read_at (dir_fd, basename, error);
+ if (fd < 0)
+ {
+ ht_util_set_error_from_errno (error, errno);
+ goto out;
+ }
+ }
+
+ stat_string = stat_to_string (out_stbuf);
+
+ /* FIXME - Add llistxattrat */
+ if (!S_ISLNK(out_stbuf->st_mode))
+ bytes_read = flistxattr (fd, NULL, 0);
+ else
+ bytes_read = llistxattr (path, NULL, 0);
+
+ if (bytes_read < 0)
+ {
+ if (errno != ENOTSUP)
+ {
+ ht_util_set_error_from_errno (error, errno);
+ goto out;
+ }
+ }
+ if (errno != ENOTSUP)
+ {
+ gboolean tmp;
+ xattrs = g_malloc (bytes_read);
+ /* FIXME - Add llistxattrat */
+ if (!S_ISLNK(out_stbuf->st_mode))
+ tmp = flistxattr (fd, xattrs, bytes_read);
+ else
+ tmp = llistxattr (path, xattrs, bytes_read);
+
+ if (!tmp)
+ {
+ ht_util_set_error_from_errno (error, errno);
+ goto out;
+ }
+
+ xattrs_canonicalized = canonicalize_xattrs (xattrs, bytes_read);
+ }
+
+ content_sha256 = g_checksum_new (G_CHECKSUM_SHA256);
+
+ if (S_ISREG(out_stbuf->st_mode))
+ {
+ guint8 buf[8192];
+
+ while ((bytes_read = read (fd, buf, sizeof (buf))) > 0)
+ g_checksum_update (content_sha256, buf, bytes_read);
+ if (bytes_read < 0)
+ {
+ ht_util_set_error_from_errno (error, errno);
+ goto out;
+ }
+ }
+ else if (S_ISLNK(out_stbuf->st_mode))
+ {
+ symlink_target = g_malloc (PATH_MAX);
+
+ if (readlinkat (dir_fd, basename, symlink_target, PATH_MAX) < 0)
+ {
+ ht_util_set_error_from_errno (error, errno);
+ goto out;
+ }
+ g_checksum_update (content_sha256, symlink_target, strlen (symlink_target));
+ }
+ else if (S_ISCHR(out_stbuf->st_mode) || S_ISBLK(out_stbuf->st_mode))
+ {
+ device_id = g_strdup_printf ("%d", out_stbuf->st_rdev);
+ g_checksum_update (content_sha256, device_id, strlen (device_id));
+ }
+ else
+ {
+ g_set_error (error, G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Unsupported file '%s' (must be regular, symbolic link, or device)",
+ path);
+ goto out;
+ }
+
+ content_and_meta_sha256 = g_checksum_copy (content_sha256);
+
+ g_checksum_update (content_and_meta_sha256, stat_string, strlen (stat_string));
+ g_checksum_update (content_and_meta_sha256, xattrs_canonicalized, strlen (stat_string));
+
+ *out_checksum = content_and_meta_sha256;
+ ret = TRUE;
+ out:
+ if (fd >= 0)
+ close (fd);
+ if (temp_dir != NULL)
+ closedir (temp_dir);
+ g_free (symlink_target);
+ g_free (basename);
+ g_free (stat_string);
+ g_free (xattrs);
+ g_free (xattrs_canonicalized);
+ if (content_sha256)
+ g_checksum_free (content_sha256);
+
+ return ret;
+}
diff --git a/src/libhacktree/hacktree-core.h b/src/libhacktree/hacktree-core.h
new file mode 100644
index 0000000..124a90a
--- /dev/null
+++ b/src/libhacktree/hacktree-core.h
@@ -0,0 +1,36 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2011 Colin Walters <walters verbum org>
+ *
+ * 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 Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Colin Walters <walters verbum org>
+ */
+/* hacktree-repo.h */
+
+#ifndef _HACKTREE_CORE
+#define _HACKTREE_CORE
+
+#include <htutil.h>
+
+G_BEGIN_DECLS
+
+gboolean hacktree_stat_and_checksum_file (int dirfd, const char *path,
+ GChecksum **out_checksum,
+ struct stat *out_stbuf,
+ GError **error);
+
+
+#endif /* _HACKTREE_REPO */
diff --git a/src/libhacktree/hacktree-repo.c b/src/libhacktree/hacktree-repo.c
index bb0a9b8..a95f92d 100644
--- a/src/libhacktree/hacktree-repo.c
+++ b/src/libhacktree/hacktree-repo.c
@@ -167,173 +167,6 @@ hacktree_repo_check (HacktreeRepo *self, GError **error)
return TRUE;
}
-char *
-stat_to_string (struct stat *stbuf)
-{
- return g_strdup_printf ("%d:%d:%d:%" G_GUINT64_FORMAT ":%" G_GUINT64_FORMAT ":%" G_GUINT64_FORMAT,
- stbuf->st_mode,
- stbuf->st_uid,
- stbuf->st_gid,
- stbuf->st_atime,
- stbuf->st_mtime,
- stbuf->st_ctime);
-}
-
-static char *
-canonicalize_xattrs (char *xattr_string, size_t len)
-{
- char *p;
- GSList *xattrs = NULL;
- GSList *iter;
- GString *result;
-
- result = g_string_new (0);
-
- p = xattr_string;
- while (p < xattr_string+len)
- {
- xattrs = g_slist_prepend (xattrs, p);
- p += strlen (p) + 1;
- }
-
- xattrs = g_slist_sort (xattrs, (GCompareFunc) strcmp);
- for (iter = xattrs; iter; iter = iter->next)
- g_string_append (result, iter->data);
-
- g_slist_free (xattrs);
- return g_string_free (result, FALSE);
-}
-
-static gboolean
-stat_and_compute_checksum (int dirfd, const char *path,
- GChecksum **out_checksum,
- struct stat *out_stbuf,
- GError **error)
-{
- GChecksum *content_sha256 = NULL;
- GChecksum *content_and_meta_sha256 = NULL;
- char *stat_string = NULL;
- ssize_t bytes_read;
- char *xattrs = NULL;
- char *xattrs_canonicalized = NULL;
- int fd = -1;
- char *basename = NULL;
- gboolean ret = FALSE;
- char *symlink_target = NULL;
- char *device_id = NULL;
-
- basename = g_path_get_basename (path);
-
- if (fstatat (dirfd, basename, out_stbuf, AT_SYMLINK_NOFOLLOW) < 0)
- {
- ht_util_set_error_from_errno (error, errno);
- goto out;
- }
-
- if (!S_ISLNK(out_stbuf->st_mode))
- {
- fd = ht_util_open_file_read_at (dirfd, basename, error);
- if (fd < 0)
- {
- ht_util_set_error_from_errno (error, errno);
- goto out;
- }
- }
-
- stat_string = stat_to_string (out_stbuf);
-
- /* FIXME - Add llistxattrat */
- if (!S_ISLNK(out_stbuf->st_mode))
- bytes_read = flistxattr (fd, NULL, 0);
- else
- bytes_read = llistxattr (path, NULL, 0);
-
- if (bytes_read < 0)
- {
- if (errno != ENOTSUP)
- {
- ht_util_set_error_from_errno (error, errno);
- goto out;
- }
- }
- if (errno != ENOTSUP)
- {
- gboolean tmp;
- xattrs = g_malloc (bytes_read);
- /* FIXME - Add llistxattrat */
- if (!S_ISLNK(out_stbuf->st_mode))
- tmp = flistxattr (fd, xattrs, bytes_read);
- else
- tmp = llistxattr (path, xattrs, bytes_read);
-
- if (!tmp)
- {
- ht_util_set_error_from_errno (error, errno);
- goto out;
- }
-
- xattrs_canonicalized = canonicalize_xattrs (xattrs, bytes_read);
- }
-
- content_sha256 = g_checksum_new (G_CHECKSUM_SHA256);
-
- if (S_ISREG(out_stbuf->st_mode))
- {
- guint8 buf[8192];
-
- while ((bytes_read = read (fd, buf, sizeof (buf))) > 0)
- g_checksum_update (content_sha256, buf, bytes_read);
- if (bytes_read < 0)
- {
- ht_util_set_error_from_errno (error, errno);
- goto out;
- }
- }
- else if (S_ISLNK(out_stbuf->st_mode))
- {
- symlink_target = g_malloc (PATH_MAX);
-
- if (readlinkat (dirfd, basename, symlink_target, PATH_MAX) < 0)
- {
- ht_util_set_error_from_errno (error, errno);
- goto out;
- }
- g_checksum_update (content_sha256, symlink_target, strlen (symlink_target));
- }
- else if (S_ISCHR(out_stbuf->st_mode) || S_ISBLK(out_stbuf->st_mode))
- {
- device_id = g_strdup_printf ("%d", out_stbuf->st_rdev);
- g_checksum_update (content_sha256, device_id, strlen (device_id));
- }
- else
- {
- g_set_error (error, G_IO_ERROR,
- G_IO_ERROR_FAILED,
- "Unsupported file '%s' (must be regular, symbolic link, or device)",
- path);
- goto out;
- }
-
- content_and_meta_sha256 = g_checksum_copy (content_sha256);
-
- g_checksum_update (content_and_meta_sha256, stat_string, strlen (stat_string));
- g_checksum_update (content_and_meta_sha256, xattrs_canonicalized, strlen (stat_string));
-
- *out_checksum = content_and_meta_sha256;
- ret = TRUE;
- out:
- if (fd >= 0)
- close (fd);
- g_free (symlink_target);
- g_free (basename);
- g_free (stat_string);
- g_free (xattrs);
- g_free (xattrs_canonicalized);
- if (content_sha256)
- g_checksum_free (content_sha256);
-
- return ret;
-}
static char *
prepare_dir_for_checksum_get_object_path (HacktreeRepo *self,
@@ -346,14 +179,14 @@ prepare_dir_for_checksum_get_object_path (HacktreeRepo *self,
char *object_path = NULL;
GError *temp_error = NULL;
- checksum_prefix = g_strdup (g_checksum_get_string (checksum));
- checksum_prefix[2] = '\0';
+ checksum_prefix = g_strndup (g_checksum_get_string (checksum), 2);
+ g_assert_cmpuint (strlen (checksum_prefix), ==, 2);
checksum_dir = g_build_filename (priv->objects_path, checksum_prefix, NULL);
if (!ht_util_ensure_directory (checksum_dir, FALSE, error))
goto out;
- object_path = g_build_filename (checksum_dir, checksum_prefix + 3, NULL);
+ object_path = g_build_filename (checksum_dir, g_checksum_get_string (checksum) + 2, NULL);
out:
g_free (checksum_prefix);
g_free (checksum_dir);
@@ -387,7 +220,7 @@ link_one_file (HacktreeRepo *self, const char *path, GError **error)
goto out;
}
- if (!stat_and_compute_checksum (dirfd (src_dir), path, &id, &stbuf, error))
+ if (!hacktree_stat_and_checksum_file (dirfd (src_dir), path, &id, &stbuf, error))
goto out;
dest_path = prepare_dir_for_checksum_get_object_path (self, id, error);
if (!dest_path)
@@ -434,3 +267,115 @@ hacktree_repo_link_file (HacktreeRepo *self,
return link_one_file (self, path, error);
}
+
+static gboolean
+iter_object_dir (HacktreeRepo *repo,
+ GFile *dir,
+ HacktreeRepoObjectIter callback,
+ gpointer user_data,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ GError *temp_error = NULL;
+ GFileEnumerator *enumerator = NULL;
+ GFileInfo *file_info = NULL;
+ char *dirpath = NULL;
+
+ dirpath = g_file_get_path (dir);
+
+ enumerator = g_file_enumerate_children (dir, "standard::*,unix::*",
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL,
+ error);
+ if (!enumerator)
+ goto out;
+
+ while ((file_info = g_file_enumerator_next_file (enumerator, NULL, &temp_error)) != NULL)
+ {
+ const char *name;
+ guint32 type;
+ name = g_file_info_get_attribute_byte_string (file_info, "standard::name");
+ type = g_file_info_get_attribute_uint32 (file_info, "standard::type");
+
+ /* 64 - 2 */
+ if (strlen (name) == 62 && type != G_FILE_TYPE_DIRECTORY)
+ {
+ char *path = g_build_filename (dirpath, name, NULL);
+ callback (repo, path, file_info, user_data);
+ g_free (path);
+ }
+
+ g_object_unref (file_info);
+ }
+ if (file_info == NULL && temp_error != NULL)
+ {
+ g_propagate_error (error, temp_error);
+ goto out;
+ }
+ if (!g_file_enumerator_close (enumerator, NULL, error))
+ goto out;
+
+ ret = TRUE;
+ out:
+ g_free (dirpath);
+ return ret;
+}
+
+gboolean
+hacktree_repo_iter_objects (HacktreeRepo *self,
+ HacktreeRepoObjectIter callback,
+ gpointer user_data,
+ GError **error)
+{
+ HacktreeRepoPrivate *priv = GET_PRIVATE (self);
+ GFile *objectdir = NULL;
+ GFileEnumerator *enumerator = NULL;
+ gboolean ret = FALSE;
+ GFileInfo *file_info = NULL;
+ GError *temp_error = NULL;
+
+ g_return_val_if_fail (priv->inited, FALSE);
+
+ objectdir = g_file_new_for_path (priv->objects_path);
+ enumerator = g_file_enumerate_children (objectdir, "standard::*,unix::*",
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL,
+ error);
+ if (!enumerator)
+ goto out;
+
+ while ((file_info = g_file_enumerator_next_file (enumerator, NULL, &temp_error)) != NULL)
+ {
+ const char *name;
+ guint32 type;
+
+ name = g_file_info_get_attribute_byte_string (file_info, "standard::name");
+ type = g_file_info_get_attribute_uint32 (file_info, "standard::type");
+
+ if (strlen (name) == 2 && type == G_FILE_TYPE_DIRECTORY)
+ {
+ GFile *objdir = g_file_get_child (objectdir, name);
+ if (!iter_object_dir (self, objdir, callback, user_data, error))
+ {
+ g_object_unref (objdir);
+ goto out;
+ }
+ g_object_unref (objdir);
+ }
+ g_object_unref (file_info);
+ }
+ if (file_info == NULL && temp_error != NULL)
+ {
+ g_propagate_error (error, temp_error);
+ goto out;
+ }
+ if (!g_file_enumerator_close (enumerator, NULL, error))
+ goto out;
+
+ ret = TRUE;
+ out:
+ g_clear_object (&file_info);
+ g_clear_object (&enumerator);
+ g_clear_object (&objectdir);
+ return ret;
+}
diff --git a/src/libhacktree/hacktree-repo.h b/src/libhacktree/hacktree-repo.h
index 715560e..0899295 100644
--- a/src/libhacktree/hacktree-repo.h
+++ b/src/libhacktree/hacktree-repo.h
@@ -57,6 +57,14 @@ gboolean hacktree_repo_link_file (HacktreeRepo *repo,
const char *path,
GError **error);
+typedef void (*HacktreeRepoObjectIter) (HacktreeRepo *repo, const char *path,
+ GFileInfo *fileinfo, gpointer user_data);
+
+gboolean hacktree_repo_iter_objects (HacktreeRepo *repo,
+ HacktreeRepoObjectIter callback,
+ gpointer user_data,
+ GError **error);
+
G_END_DECLS
#endif /* _HACKTREE_REPO */
diff --git a/src/libhacktree/hacktree.h b/src/libhacktree/hacktree.h
index 11f0a89..0cf2f15 100644
--- a/src/libhacktree/hacktree.h
+++ b/src/libhacktree/hacktree.h
@@ -21,6 +21,7 @@
#ifndef __HACKTREE_H__
+#include <hacktree-core.h>
#include <hacktree-repo.h>
#include <hacktree-types.h>
diff --git a/src/libhtutil/ht-unix-utils.c b/src/libhtutil/ht-unix-utils.c
index f0aebb2..4637c7d 100644
--- a/src/libhtutil/ht-unix-utils.c
+++ b/src/libhtutil/ht-unix-utils.c
@@ -30,7 +30,6 @@
#include <sys/types.h>
#include <dirent.h>
-
void
ht_util_set_error_from_errno (GError **error,
gint saved_errno)
diff --git a/src/main.c b/src/main.c
index df4022e..7ff1c24 100644
--- a/src/main.c
+++ b/src/main.c
@@ -31,6 +31,7 @@
static HacktreeBuiltin builtins[] = {
{ "init", hacktree_builtin_init, 0 },
{ "link-file", hacktree_builtin_link_file, 0 },
+ { "fsck", hacktree_builtin_fsck, 0 },
{ NULL }
};
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]