Merge branch 'mh/check-attr-relative'
authorJunio C Hamano <gitster@pobox.com>
Thu, 18 Aug 2011 00:36:22 +0000 (17:36 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 18 Aug 2011 00:36:22 +0000 (17:36 -0700)
* mh/check-attr-relative: (29 commits)
test-path-utils: Add subcommand "prefix_path"
test-path-utils: Add subcommand "absolute_path"
git-check-attr: Normalize paths
git-check-attr: Demonstrate problems with relative paths
git-check-attr: Demonstrate problems with unnormalized paths
git-check-attr: test that no output is written to stderr
Rename git_checkattr() to git_check_attr()
git-check-attr: Fix command-line handling to match docs
git-check-attr: Drive two tests using the same raw data
git-check-attr: Add an --all option to show all attributes
git-check-attr: Error out if no pathnames are specified
git-check-attr: Process command-line args more systematically
git-check-attr: Handle each error separately
git-check-attr: Extract a function error_with_usage()
git-check-attr: Introduce a new variable
git-check-attr: Extract a function output_attr()
Allow querying all attributes on a file
Remove redundant check
Remove redundant call to bootstrap_attr_stack()
Extract a function collect_all_attrs()
...

1  2 
Documentation/gitattributes.txt
builtin/pack-objects.c
index 2bbe76b5d88e4a38f22bdaef8612a48ddf1fe8ba,3d8643437e7f451b2675ae52902bc68a58f2b02f..25e46aeb7a32287c7dc2666d2633c4787ae1c59a
@@@ -79,7 -79,7 +79,7 @@@ Attributes for all users on a system sh
  `$(prefix)/etc/gitattributes` file.
  
  Sometimes you would need to override an setting of an attribute
 -for a path to `unspecified` state.  This can be done by listing
 +for a path to `Unspecified` state.  This can be done by listing
  the name of the attribute prefixed with an exclamation point `!`.
  
  
@@@ -868,7 -868,7 +868,7 @@@ If this attribute is not set or has an 
  (See linkgit:git-config[1]).
  
  
 -USING ATTRIBUTE MACROS
 +USING MACRO ATTRIBUTES
  ----------------------
  
  You do not want any end-of-line conversions applied to, nor textual diffs
@@@ -879,27 -879,24 +879,27 @@@ produced for, any binary file you track
  ------------
  
  but that may become cumbersome, when you have many attributes.  Using
 -attribute macros, you can specify groups of attributes set or unset at
 -the same time.  The system knows a built-in attribute macro, `binary`:
 +macro attributes, you can define an attribute that, when set, also
 +sets or unsets a number of other attributes at the same time.  The
 +system knows a built-in macro attribute, `binary`:
  
  ------------
  *.jpg binary
  ------------
  
 -which is equivalent to the above.  Note that the attribute macros can only
 -be "Set" (see the above example that sets "binary" macro as if it were an
 -ordinary attribute --- setting it in turn unsets "text" and "diff").
 +Setting the "binary" attribute also unsets the "text" and "diff"
 +attributes as above.  Note that macro attributes can only be "Set",
 +though setting one might have the effect of setting or unsetting other
 +attributes or even returning other attributes to the "Unspecified"
 +state.
  
  
 -DEFINING ATTRIBUTE MACROS
 +DEFINING MACRO ATTRIBUTES
  -------------------------
  
 -Custom attribute macros can be defined only in the `.gitattributes` file
 -at the toplevel (i.e. not in any subdirectory).  The built-in attribute
 -macro "binary" is equivalent to:
 +Custom macro attributes can be defined only in the `.gitattributes`
 +file at the toplevel (i.e. not in any subdirectory).  The built-in
 +macro attribute "binary" is equivalent to:
  
  ------------
  [attr]binary -diff -text
@@@ -955,6 -952,9 +955,9 @@@ frotz      unspecifie
  ----------------------------------------------------------------
  
  
+ SEE ALSO
+ --------
+ linkgit:git-check-attr[1].
  
  GIT
  ---
diff --combined builtin/pack-objects.c
index 27f24d3aafbee239301628a2649dca83fcd12081,ac8bed8aa1a704e81192b43beb5fe1ca5b805e85..a9c67c18ba159c8f04fa6bfff52ed9718965190a
@@@ -51,8 -51,6 +51,8 @@@ struct object_entry 
                                       * objects against.
                                       */
        unsigned char no_try_delta;
 +      unsigned char tagged; /* near the very tip of refs */
 +      unsigned char filled; /* assigned write-order */
  };
  
  /*
@@@ -98,7 -96,6 +98,7 @@@ static unsigned long window_memory_limi
   */
  static int *object_ix;
  static int object_ix_hashsz;
 +static struct object_entry *locate_object_entry(const unsigned char *sha1);
  
  /*
   * stats
@@@ -203,7 -200,6 +203,7 @@@ static void copy_pack_data(struct sha1f
        }
  }
  
 +/* Return 0 if we will bust the pack-size limit */
  static unsigned long write_object(struct sha1file *f,
                                  struct object_entry *entry,
                                  off_t write_offset)
@@@ -438,134 -434,6 +438,134 @@@ static int write_one(struct sha1file *f
        return 1;
  }
  
 +static int mark_tagged(const char *path, const unsigned char *sha1, int flag,
 +                     void *cb_data)
 +{
 +      unsigned char peeled[20];
 +      struct object_entry *entry = locate_object_entry(sha1);
 +
 +      if (entry)
 +              entry->tagged = 1;
 +      if (!peel_ref(path, peeled)) {
 +              entry = locate_object_entry(peeled);
 +              if (entry)
 +                      entry->tagged = 1;
 +      }
 +      return 0;
 +}
 +
 +static void add_to_write_order(struct object_entry **wo,
 +                             int *endp,
 +                             struct object_entry *e)
 +{
 +      if (e->filled)
 +              return;
 +      wo[(*endp)++] = e;
 +      e->filled = 1;
 +}
 +
 +static void add_descendants_to_write_order(struct object_entry **wo,
 +                                         int *endp,
 +                                         struct object_entry *e)
 +{
 +      struct object_entry *child;
 +
 +      for (child = e->delta_child; child; child = child->delta_sibling)
 +              add_to_write_order(wo, endp, child);
 +      for (child = e->delta_child; child; child = child->delta_sibling)
 +              add_descendants_to_write_order(wo, endp, child);
 +}
 +
 +static void add_family_to_write_order(struct object_entry **wo,
 +                                    int *endp,
 +                                    struct object_entry *e)
 +{
 +      struct object_entry *root;
 +
 +      for (root = e; root->delta; root = root->delta)
 +              ; /* nothing */
 +      add_to_write_order(wo, endp, root);
 +      add_descendants_to_write_order(wo, endp, root);
 +}
 +
 +static struct object_entry **compute_write_order(void)
 +{
 +      int i, wo_end;
 +
 +      struct object_entry **wo = xmalloc(nr_objects * sizeof(*wo));
 +
 +      for (i = 0; i < nr_objects; i++) {
 +              objects[i].tagged = 0;
 +              objects[i].filled = 0;
 +              objects[i].delta_child = NULL;
 +              objects[i].delta_sibling = NULL;
 +      }
 +
 +      /*
 +       * Fully connect delta_child/delta_sibling network.
 +       * Make sure delta_sibling is sorted in the original
 +       * recency order.
 +       */
 +      for (i = nr_objects - 1; 0 <= i; i--) {
 +              struct object_entry *e = &objects[i];
 +              if (!e->delta)
 +                      continue;
 +              /* Mark me as the first child */
 +              e->delta_sibling = e->delta->delta_child;
 +              e->delta->delta_child = e;
 +      }
 +
 +      /*
 +       * Mark objects that are at the tip of tags.
 +       */
 +      for_each_tag_ref(mark_tagged, NULL);
 +
 +      /*
 +       * Give the commits in the original recency order until
 +       * we see a tagged tip.
 +       */
 +      for (i = wo_end = 0; i < nr_objects; i++) {
 +              if (objects[i].tagged)
 +                      break;
 +              add_to_write_order(wo, &wo_end, &objects[i]);
 +      }
 +
 +      /*
 +       * Then fill all the tagged tips.
 +       */
 +      for (; i < nr_objects; i++) {
 +              if (objects[i].tagged)
 +                      add_to_write_order(wo, &wo_end, &objects[i]);
 +      }
 +
 +      /*
 +       * And then all remaining commits and tags.
 +       */
 +      for (i = 0; i < nr_objects; i++) {
 +              if (objects[i].type != OBJ_COMMIT &&
 +                  objects[i].type != OBJ_TAG)
 +                      continue;
 +              add_to_write_order(wo, &wo_end, &objects[i]);
 +      }
 +
 +      /*
 +       * And then all the trees.
 +       */
 +      for (i = 0; i < nr_objects; i++) {
 +              if (objects[i].type != OBJ_TREE)
 +                      continue;
 +              add_to_write_order(wo, &wo_end, &objects[i]);
 +      }
 +
 +      /*
 +       * Finally all the rest in really tight order
 +       */
 +      for (i = 0; i < nr_objects; i++)
 +              add_family_to_write_order(wo, &wo_end, &objects[i]);
 +
 +      return wo;
 +}
 +
  static void write_pack_file(void)
  {
        uint32_t i = 0, j;
        struct pack_header hdr;
        uint32_t nr_remaining = nr_result;
        time_t last_mtime = 0;
 +      struct object_entry **write_order;
  
        if (progress > pack_to_stdout)
                progress_state = start_progress("Writing objects", nr_result);
        written_list = xmalloc(nr_objects * sizeof(*written_list));
 +      write_order = compute_write_order();
  
        do {
                unsigned char sha1[20];
                offset = sizeof(hdr);
                nr_written = 0;
                for (; i < nr_objects; i++) {
 -                      if (!write_one(f, objects + i, &offset))
 +                      struct object_entry *e = write_order[i];
 +                      if (!write_one(f, e, &offset))
                                break;
                        display_progress(progress_state, written);
                }
        } while (nr_remaining && i < nr_objects);
  
        free(written_list);
 +      free(write_order);
        stop_progress(&progress_state);
        if (written != nr_result)
                die("wrote %"PRIu32" objects while expecting %"PRIu32,
@@@ -770,7 -634,7 +770,7 @@@ static int no_try_delta(const char *pat
        struct git_attr_check check[1];
  
        setup_delta_attr_check(check);
-       if (git_checkattr(path, ARRAY_SIZE(check), check))
+       if (git_check_attr(path, ARRAY_SIZE(check), check))
                return 0;
        if (ATTR_FALSE(check->value))
                return 1;