From: Jeff Hostetler <git@jeffhostetler.com>
To: git@vger.kernel.org
Cc: gitster@pobox.com, peff@peff.net, jonathantanmy@google.com,
Jeff Hostetler <jeffhost@microsoft.com>
Subject: [PATCH 07/13] object-filter: common declarations for object filtering
Date: Fri, 22 Sep 2017 20:30:11 +0000 [thread overview]
Message-ID: <20170922203017.53986-8-git@jeffhostetler.com> (raw)
In-Reply-To: <20170922203017.53986-6-git@jeffhostetler.com>
From: Jeff Hostetler <jeffhost@microsoft.com>
Create common routines and defines for parsing
object-filter-related command line arguments and
pack-protocol fields.
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
---
Makefile | 1 +
object-filter.c | 269 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
object-filter.h | 173 ++++++++++++++++++++++++++++++++++++
3 files changed, 443 insertions(+)
create mode 100644 object-filter.c
create mode 100644 object-filter.h
diff --git a/Makefile b/Makefile
index 6e0bd91..bddd6b5 100644
--- a/Makefile
+++ b/Makefile
@@ -818,6 +818,7 @@ LIB_OBJS += notes-cache.o
LIB_OBJS += notes-merge.o
LIB_OBJS += notes-utils.o
LIB_OBJS += object.o
+LIB_OBJS += object-filter.o
LIB_OBJS += oidset.o
LIB_OBJS += oidset2.o
LIB_OBJS += pack-bitmap.o
diff --git a/object-filter.c b/object-filter.c
new file mode 100644
index 0000000..c88f79f
--- /dev/null
+++ b/object-filter.c
@@ -0,0 +1,269 @@
+#include "cache.h"
+#include "commit.h"
+#include "config.h"
+#include "revision.h"
+#include "list-objects.h"
+#include "oidset2.h"
+#include "list-objects-filter-all.h"
+#include "list-objects-filter-large.h"
+#include "list-objects-filter-sparse.h"
+#include "object-filter.h"
+
+int parse_filter_omit_all_blobs(struct object_filter_options *filter_options)
+{
+ if (object_filter_enabled(filter_options))
+ die(_("multiple object filter types cannot be combined"));
+
+ filter_options->omit_all_blobs = 1;
+ return 0;
+}
+
+int parse_filter_omit_large_blobs(struct object_filter_options *filter_options,
+ const char *arg)
+{
+ if (object_filter_enabled(filter_options))
+ die(_("multiple object filter types cannot be combined"));
+
+ filter_options->omit_large_blobs = 1;
+
+ /* we allow "<digits>[kmg]" */
+ if (!git_parse_ulong(arg, &filter_options->large_byte_limit))
+ die(_("invalid size limit for large object filter"));
+
+ filter_options->large_byte_limit_string = strdup(arg);
+ return 0;
+}
+
+int parse_filter_use_blob(struct object_filter_options *filter_options,
+ const char *arg)
+{
+ struct object_context oc;
+
+ if (object_filter_enabled(filter_options))
+ die(_("multiple object filter types cannot be combined"));
+
+ filter_options->use_blob = 1;
+
+ /*
+ * The command line argument needs to resolve to an known OID
+ * representing the content of the desired sparse-checkout file.
+ *
+ * We allow various syntax forms for the convenience of the user.
+ * See sha1_name.c:get_sha1_with_context_1().
+ *
+ * Try to evaluate the arg locally in case they use one of the
+ * convenience patterns. This must resolve to a blob.
+ */
+ if (get_sha1_with_context(arg, GET_SHA1_BLOB,
+ filter_options->sparse_oid.hash, &oc)) {
+ /*
+ * If that fails, keep the original string in case a client
+ * command wants to send it to the server. This allows the
+ * client to name an OID for a blob they don't have.
+ */
+ filter_options->sparse_value = strdup(arg);
+ oidcpy(&filter_options->sparse_oid, &null_oid);
+ } else {
+ /*
+ * Round-trip the found OID to normalize it.
+ */
+ filter_options->sparse_value =
+ strdup(oid_to_hex(&filter_options->sparse_oid));
+ }
+ return 0;
+}
+
+int parse_filter_use_path(struct object_filter_options *filter_options,
+ const char *arg)
+{
+ if (object_filter_enabled(filter_options))
+ die(_("multiple object filter types cannot be combined"));
+
+ filter_options->use_path = 1;
+
+ /*
+ * The command line argument needs to resolve to a local file
+ * containing the content of the desired sparse-checkout file.
+ */
+ filter_options->sparse_value = strdup(arg);
+ return 0;
+}
+
+int parse_filter_print_omitted(struct object_filter_options *filter_options)
+{
+ filter_options->print_omitted = 1;
+ return 0;
+}
+
+int parse_filter_print_missing(struct object_filter_options *filter_options)
+{
+ filter_options->print_missing = 1;
+ return 0;
+}
+
+int parse_filter_relax(struct object_filter_options *filter_options)
+{
+ filter_options->relax = 1;
+ return 0;
+}
+
+int opt_parse_filter_omit_all_blobs(const struct option *opt,
+ const char *arg, int unset)
+{
+ struct object_filter_options *filter_options = opt->value;
+
+ assert(!arg);
+ assert(!unset);
+
+ return parse_filter_omit_all_blobs(filter_options);
+}
+
+int opt_parse_filter_omit_large_blobs(const struct option *opt,
+ const char *arg, int unset)
+{
+ struct object_filter_options *filter_options = opt->value;
+
+ assert(arg);
+ assert(!unset);
+
+ return parse_filter_omit_large_blobs(filter_options, arg);
+}
+
+int opt_parse_filter_use_blob(const struct option *opt,
+ const char *arg, int unset)
+{
+ struct object_filter_options *filter_options = opt->value;
+
+ assert(arg);
+ assert(!unset);
+
+ return parse_filter_use_blob(filter_options, arg);
+}
+
+int opt_parse_filter_use_path(const struct option *opt,
+ const char *arg, int unset)
+{
+ struct object_filter_options *filter_options = opt->value;
+
+ assert(arg);
+ assert(!unset);
+
+ return parse_filter_use_path(filter_options, arg);
+}
+
+int opt_parse_filter_print_omitted(const struct option *opt,
+ const char *arg, int unset)
+{
+ struct object_filter_options *filter_options = opt->value;
+
+ assert(!arg);
+ assert(!unset);
+
+ return parse_filter_print_omitted(filter_options);
+}
+
+int opt_parse_filter_print_missing(const struct option *opt,
+ const char *arg, int unset)
+{
+ struct object_filter_options *filter_options = opt->value;
+
+ assert(!arg);
+ assert(!unset);
+
+ return parse_filter_print_missing(filter_options);
+}
+
+int opt_parse_filter_relax(const struct option *opt,
+ const char *arg, int unset)
+{
+ struct object_filter_options *filter_options = opt->value;
+
+ assert(!arg);
+ assert(!unset);
+
+ return parse_filter_relax(filter_options);
+}
+
+int object_filter_hand_parse_arg(struct object_filter_options *filter_options,
+ const char *arg,
+ int allow_print_omitted,
+ int allow_print_missing,
+ int allow_relax)
+{
+ if (!strcmp(arg, ("--"CL_ARG_FILTER_OMIT_ALL_BLOBS))) {
+ parse_filter_omit_all_blobs(filter_options);
+ return 1;
+ }
+ if (skip_prefix(arg, ("--"CL_ARG_FILTER_OMIT_LARGE_BLOBS"="), &arg)) {
+ parse_filter_omit_large_blobs(filter_options, arg);
+ return 1;
+ }
+ if (skip_prefix(arg, ("--"CL_ARG_FILTER_USE_BLOB"="), &arg)) {
+ parse_filter_use_blob(filter_options, arg);
+ return 1;
+ }
+ if (skip_prefix(arg, ("--"CL_ARG_FILTER_USE_PATH"="), &arg)) {
+ parse_filter_use_path(filter_options, arg);
+ return 1;
+ }
+
+ if (allow_print_omitted &&
+ !strcmp(arg, ("--"CL_ARG_FILTER_PRINT_OMITTED))) {
+ parse_filter_print_omitted(filter_options);
+ return 1;
+ }
+
+ if (allow_print_missing &&
+ !strcmp(arg, ("--"CL_ARG_FILTER_PRINT_MISSING))) {
+ parse_filter_print_missing(filter_options);
+ return 1;
+ }
+
+ if (allow_relax && !strcmp(arg, ("--"CL_ARG_FILTER_RELAX))) {
+ parse_filter_relax(filter_options);
+ return 1;
+ }
+
+ return 0;
+}
+
+int object_filter_hand_parse_protocol(struct object_filter_options *filter_options,
+ const char *arg,
+ int allow_print_omitted,
+ int allow_print_missing,
+ int allow_relax)
+{
+ if (!strcmp(arg, CL_ARG_FILTER_OMIT_ALL_BLOBS)) {
+ parse_filter_omit_all_blobs(filter_options);
+ return 1;
+ }
+ if (skip_prefix(arg, (CL_ARG_FILTER_OMIT_LARGE_BLOBS" "), &arg)) {
+ parse_filter_omit_large_blobs(filter_options, arg);
+ return 1;
+ }
+ if (skip_prefix(arg, (CL_ARG_FILTER_USE_BLOB" "), &arg)) {
+ parse_filter_use_blob(filter_options, arg);
+ return 1;
+ }
+ if (skip_prefix(arg, (CL_ARG_FILTER_USE_PATH" "), &arg)) {
+ parse_filter_use_path(filter_options, arg);
+ return 1;
+ }
+
+ if (allow_print_omitted &&
+ !strcmp(arg, CL_ARG_FILTER_PRINT_OMITTED)) {
+ parse_filter_print_omitted(filter_options);
+ return 1;
+ }
+ if (allow_print_missing &&
+ !strcmp(arg, CL_ARG_FILTER_PRINT_MISSING)) {
+ parse_filter_print_missing(filter_options);
+ return 1;
+ }
+ if (allow_relax && !strcmp(arg, CL_ARG_FILTER_RELAX)) {
+ parse_filter_relax(filter_options);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/object-filter.h b/object-filter.h
new file mode 100644
index 0000000..13a638b
--- /dev/null
+++ b/object-filter.h
@@ -0,0 +1,173 @@
+#ifndef OBJECT_FILTER_H
+#define OBJECT_FILTER_H
+
+#include "parse-options.h"
+
+/*
+ * Common declarations and utilities for filtering objects (such as omitting
+ * large blobs) in list_objects:traverse_commit_list() and git-rev-list.
+ */
+
+struct object_filter_options {
+ /*
+ * File pathname or blob-ish path/OID (that get_sha1_with_context() can
+ * use to find the blob containing the sparse-checkout specification.
+ * This is only used when use_blob or use_path is set.
+ */
+ const char *sparse_value;
+ struct object_id sparse_oid;
+
+ /*
+ * Blob size byte limit for filtering. Only blobs smaller than this
+ * value will be included. A value of zero, omits all blobs.
+ * only used when omit_large_blobs is set. Integer and string versions
+ * of this are kept for convenience. The string version may contain
+ * a [kmg] suffix.
+ */
+ unsigned long large_byte_limit;
+ const char *large_byte_limit_string;
+
+ /* Valid filter types (only one may be used at a time) */
+ unsigned omit_all_blobs : 1;
+ unsigned omit_large_blobs : 1;
+ unsigned use_blob : 1;
+ unsigned use_path : 1;
+
+ /*
+ * True if rev-list should print a list of the objects omitted
+ * by this invocation of a filter.
+ */
+ unsigned print_omitted : 1;
+
+ /*
+ * True if rev-list should print a list of missing objects.
+ * Objects can be missing because of a previously filtered
+ * clone or fetch. The set reported here can also be filtered
+ * by the current filter in effect.
+ */
+ unsigned print_missing : 1;
+
+ /* True to suppress missing object errors during consistency checks */
+ unsigned relax : 1;
+};
+
+/*
+ * Return true if a filter is enabled.
+ */
+inline int object_filter_enabled(const struct object_filter_options *p)
+{
+ return p->omit_all_blobs ||
+ p->omit_large_blobs ||
+ p->use_blob ||
+ p->use_path;
+}
+
+/* Normalized command line arguments */
+#define CL_ARG_FILTER_OMIT_ALL_BLOBS "filter-omit-all-blobs"
+#define CL_ARG_FILTER_OMIT_LARGE_BLOBS "filter-omit-large-blobs"
+#define CL_ARG_FILTER_USE_BLOB "filter-use-blob"
+#define CL_ARG_FILTER_USE_PATH "filter-use-path"
+#define CL_ARG_FILTER_PRINT_OMITTED "filter-print-omitted"
+#define CL_ARG_FILTER_PRINT_MISSING "filter-print-missing"
+#define CL_ARG_FILTER_RELAX "filter-relax"
+
+/*
+ * Common command line argument parsing for object-filter-related
+ * arguments (whether from a hand-parsed or parse-options style
+ * parser.
+ */
+int parse_filter_omit_all_blobs(struct object_filter_options *filter_options);
+int parse_filter_omit_large_blobs(struct object_filter_options *filter_options,
+ const char *arg);
+int parse_filter_use_blob(struct object_filter_options *filter_options,
+ const char *arg);
+int parse_filter_use_path(struct object_filter_options *filter_options,
+ const char *arg);
+int parse_filter_print_omitted(struct object_filter_options *filter_options);
+int parse_filter_print_missing(struct object_filter_options *filter_options);
+int parse_filter_relax(struct object_filter_options *filter_options);
+
+/*
+ * Common command line argument parsers for object-filter-related
+ * arguments comming from parse-options style parsers.
+ */
+
+int opt_parse_filter_omit_all_blobs(const struct option *opt,
+ const char *arg, int unset);
+int opt_parse_filter_omit_large_blobs(const struct option *opt,
+ const char *arg, int unset);
+int opt_parse_filter_use_blob(const struct option *opt,
+ const char *arg, int unset);
+int opt_parse_filter_use_path(const struct option *opt,
+ const char *arg, int unset);
+int opt_parse_filter_print_omitted(const struct option *opt,
+ const char *arg, int unset);
+int opt_parse_filter_print_missing(const struct option *opt,
+ const char *arg, int unset);
+int opt_parse_filter_relax(const struct option *opt,
+ const char *arg, int unset);
+
+#define OPT_PARSE_FILTER_OMIT_ALL_BLOBS(fo) \
+ { OPTION_CALLBACK, 0, CL_ARG_FILTER_OMIT_ALL_BLOBS, fo, NULL, \
+ N_("omit all blobs from result"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, \
+ opt_parse_filter_omit_all_blobs }
+
+#define OPT_PARSE_FILTER_OMIT_LARGE_BLOBS(fo) \
+ { OPTION_CALLBACK, 0, CL_ARG_FILTER_OMIT_LARGE_BLOBS, fo, N_("size"), \
+ N_("omit large blobs from result"), PARSE_OPT_NONEG, \
+ opt_parse_filter_omit_large_blobs }
+
+#define OPT_PARSE_FILTER_USE_BLOB(fo) \
+ { OPTION_CALLBACK, 0, CL_ARG_FILTER_USE_BLOB, fo, N_("object"), \
+ N_("filter results using sparse-checkout specification"), PARSE_OPT_NONEG, \
+ opt_parse_filter_use_blob }
+
+#define OPT_PARSE_FILTER_USE_PATH(fo) \
+ { OPTION_CALLBACK, 0, CL_ARG_FILTER_USE_PATH, fo, N_("path"), \
+ N_("filter results using sparse-checkout specification"), PARSE_OPT_NONEG, \
+ opt_parse_filter_use_path }
+
+#define OPT_PARSE_FILTER_PRINT_OMITTED(fo) \
+ { OPTION_CALLBACK, 0, CL_ARG_FILTER_PRINT_OMITTED, fo, NULL, \
+ N_("print list of omitted objects"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, \
+ opt_parse_filter_print_omitted }
+
+#define OPT_PARSE_FILTER_PRINT_MISSING(fo) \
+ { OPTION_CALLBACK, 0, CL_ARG_FILTER_PRINT_MISSING, fo, NULL, \
+ N_("print list of missing objects"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, \
+ opt_parse_filter_print_missing }
+
+#define OPT_PARSE_FILTER_RELAX(fo) \
+ { OPTION_CALLBACK, 0, CL_ARG_FILTER_RELAX, fo, NULL, \
+ N_("relax consistency checks for previously omitted objects"), \
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG, opt_parse_filter_relax }
+
+/*
+ * Hand parse known object-filter command line options.
+ * Use this when the caller DOES NOT use the normal OPT_
+ * routines.
+ *
+ * Here we assume args of the form "--<key>" or "--<key>=<value>".
+ * Note the literal dash-dash and equals.
+ *
+ * Returns 1 if we handled the argument.
+ */
+int object_filter_hand_parse_arg(struct object_filter_options *filter_options,
+ const char *arg,
+ int allow_print_omitted,
+ int allow_print_missing,
+ int allow_relax);
+
+/*
+ * Hand parse known object-filter protocol lines.
+ *
+ * Here we assume args of the form "<key>" or "<key> <value>".
+ * Note the literal space before between the key and value.
+ */
+int object_filter_hand_parse_protocol(struct object_filter_options *filter_options,
+ const char *arg,
+ int allow_print_omitted,
+ int allow_print_missing,
+ int allow_relax);
+
+#endif /* OBJECT_FILTER_H */
--
2.9.3
next prev parent reply other threads:[~2017-09-22 20:31 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-09-22 20:30 [PATCH 05/13] list-objects-filter-large: add large blob filter to list-objects Jeff Hostetler
2017-09-22 20:30 ` [PATCH 06/13] list-objects-filter-sparse: add sparse-checkout based filter Jeff Hostetler
2017-09-22 20:30 ` Jeff Hostetler [this message]
2017-09-26 22:39 ` [PATCH 07/13] object-filter: common declarations for object filtering Jonathan Tan
2017-09-27 17:09 ` Jeff Hostetler
2017-09-28 0:05 ` Jonathan Tan
2017-09-28 14:33 ` Jeff Hostetler
2017-09-29 19:47 ` Jonathan Tan
2017-09-22 20:30 ` [PATCH 08/13] list-objects: add traverse_commit_list_filtered method Jeff Hostetler
2017-09-22 20:30 ` [PATCH 09/13] rev-list: add object filtering support Jeff Hostetler
2017-09-26 22:44 ` Jonathan Tan
2017-09-27 17:26 ` Jeff Hostetler
2017-09-22 20:30 ` [PATCH 10/13] rev-list: add filtering help text Jeff Hostetler
2017-09-22 20:30 ` [PATCH 11/13] t6112: rev-list object filtering test Jeff Hostetler
2017-09-22 20:30 ` [PATCH 12/13] pack-objects: add object filtering support Jeff Hostetler
2017-09-22 20:30 ` [PATCH 13/13] pack-objects: add filtering help text Jeff Hostetler
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170922203017.53986-8-git@jeffhostetler.com \
--to=git@jeffhostetler.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=jeffhost@microsoft.com \
--cc=jonathantanmy@google.com \
--cc=peff@peff.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).