{"thread":{"id":"7037","subject":"[PATCH] Quick description of possible gitattributes system","startedAt":"2007-03-01T12:06:47Z","lastAt":"2007-03-03T20:27:55Z","messageCount":20,"participants":["Andy Parkins","Brian Gernhardt","Robin Rosenberg","Junio C Hamano","Jakub Narebski","Linus Torvalds","Johannes Schindelin"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"35973","messageId":"200703011206.47213.andyparkins@gmail.com","threadId":"7037","inReplyTo":null,"subject":"[PATCH] Quick description of possible gitattributes system","fromName":"Andy Parkins","fromEmail":"andyparkins@gmail.com","sentAt":"2007-03-01T12:06:47Z","receivedAt":"2007-03-01T12:06:47Z","isPatch":true,"sender":{"key":"andyparkins@gmail.com","avatar":null},"body":"Junio was working on a gitattributes system.  Rather than be useful and\nwrite code, I wrote this document to show how an attribute system might\nwork.\n\nThe ideas in this document come primarily from the \"unresolved issues\"\nthread from the git mailing list.  gmane/28388.  In particular, from:\n - Brian Gernhardt\n - Johannes Schindelin\n - Junio Hamano\n - Linus Torvalds\n - Martin Waitz\n - Nicolas Pitre\n - Robin Rosenberg\n - Theodore Tso\nSo they deserve the credit for the ideas, and I deserve the blame for\nthe description.\n\nSigned-off-by: Andy Parkins <andyparkins@gmail.com>\n---\nThis one is better.  I've included some of the points raised in the\n\"unresolved issues\" thread from January.\n\n Documentation/attributes.txt |  222 ++++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 222 insertions(+), 0 deletions(-)\n create mode 100644 Documentation/attributes.txt\n\ndiff --git a/Documentation/attributes.txt b/Documentation/attributes.txt\nnew file mode 100644\nindex 0000000..9877786\n--- /dev/null\n+++ b/Documentation/attributes.txt\n@@ -0,0 +1,222 @@\n+Git Attributes System\n+=====================\n+\n+This document is a work-in-progress.  It's only purpose is to assemble\n+attribute ideas into one place.\n+\n+== Attributes\n+\n+Individual paths are assigned attributes.  Typically they will only have\n+one attribute, typically named after the corresponding mime type of that\n+file.  However, it is not required that the attribute be a mime type nor\n+is it required that this be the only attribute.\n+\n+Attributes are attached to paths in one of two ways:\n+\n+ - Via the .gitattributes file.  This will work in the same way as the\n+   .gitignore file.  That is, there can be multiple .gitattributes files\n+   throughout the working directory.\n+\n+   Typically the .gitattributes file will be a version controlled file,\n+   just like .gitignore.\n+\n+   The format of this file will be similar to .gitignore.  \"#\" starting\n+   a comment.  Globbing allowed.  Paths to subdirectories allowed.  Each\n+   path will be followed by the list of attributes that applies to that\n+   path.  Additionally, we would probably want a way of disabling an\n+   attribute.  For example\n+\n+   -------------------------------------\n+   # Sample .gitattributes file\n+   *.png image/png\n+   *.txt text/plain\n+   *.c text/plain source-file\n+   script/*.sh text/plain source-file\n+   # Disable text/plain for a particular file\n+   file-isnt-text-despite-extension.txt !text/plain\n+   -------------------------------------\n+\n+ - Via the git configuration file system.  i.e. /etc/gitconfig,\n+   $HOME/.gitconfig and $GIT_DIR/config.\n+\n+   This supplies the same facility as the .gitattributes file but allows\n+   the attributes to be specifed out-of-tree.  This will give the\n+   advantage that standard attributes can be specified per-system via\n+   /etc/gitconfig; per-user via $HOME/config or per-repository via\n+   $GIT_DIR/config.\n+\n+   It will obviously be of different format from the .gitattributes\n+   file, but the attribute names and path specification will be\n+   identical (and specified as if from the root of the repository tree).\n+   For example:\n+\n+   ------------------------------------\n+   [attributes \"*.png\"]\n+       attribute = image/png\n+   [attributes \"*.c\"]\n+       attribute = text/plain\n+\t   attribute = source-file\n+   ------------------------------------\n+\n+   (This is pretty ugly, because of the \"*\" and \".\" in the section name,\n+   however I can't think of another way of doing this without resorting to\n+   just copying the format of the .gitattributes file; like\n+   -------------------------------------\n+   [attributes]\n+       path = *.png image/png\n+\t   path = *.txt text/plain\n+\t   path = *.c text/plain source-file\n+   -------------------------------------\n+   but perhaps people would like that more?)\n+\n+With these two in place, attributes for files can be specified and\n+overridden easily.  The priority of the various files will be (from\n+lowest to highest)\n+\n+ - /etc/gitconfig\n+ - $HOME/.gitconfig\n+ - .gitattributes\n+ - $GIT_DIR/config\n+\n+The $GIT_DIR/config file is highest priority so that a user can always\n+override an attribute that is in a .gitattributes managed by someone\n+else.\n+\n+\n+== Handlers\n+\n+At this point git would be in a position to answer the question \"what\n+attributes does this file have?\" for any file in the tree.\n+\n+The handler system will allow us to specify operations that should be\n+performed on files with particular attributes.  For example, we might\n+want to have text files automatically filtered to match local line\n+ending conditions.\n+\n+----------------------------------------\n+[handler \"fix-line-endings\"]\n+  attribute = text/plain\n+  infilter = eol_lf\n+  outfilter = eol_local\n+----------------------------------------\n+\n+This definition creates a handler named \"fix-line-endings\" (don't suppose\n+they actually need names) that would run the \"eol_lf\" filter on check\n+in, and the \"eol_local\" filter on checkout.\n+\n+Similarly, we might want to tell git-show how to show images:\n+\n+----------------------------------------\n+[handler \"show-images\"]\n+  attribute = image/png\n+  attribute = image/jpeg\n+  attribute = image/gif\n+  prettyfilter = pipe display -\n+----------------------------------------\n+\n+With this filter in place,\n+----------------------------------------\n+ $ git-show v1.0.0:images/picture.png\n+----------------------------------------\n+Would run \"display -\" and pipe the picture to it.\n+\n+Multiple filters can be supplied, and order will be important.  So, to\n+transparently decompress a file and fix the line endings for a text file\n+we might do:\n+\n+---------------------------------------\n+[handler \"decompress-text\"]\n+  attribute = compressed-text\n+  infilter = gunzip\n+  infilter = eol_lf\n+  outfilter = eol_local\n+  outfilter = gzip\n+---------------------------------------\n+\n+This might be useful for documentation files that come compressed (like\n+README.gz used by Debian).\n+\n+Similarly, we might want to be able to look at compressed files stored\n+in the repository:\n+\n+---------------------------------------\n+[handler \"show-compressed-file\"]\n+  attribute = application/gzip\n+  prettyfilter = gunzip\n+  prettyfilter = eol_auto\n+---------------------------------------\n+\n+=== Handler Types\n+\n+ - infilter\n+   Run by git-add when content is added to the repository.\n+ - outfilter\n+   Run by git-checkout or git-reset when copying content from the index\n+   to the working directory.  (Actually, more likely this would be done\n+   at low level in git-read-tree)\n+ - prettyfilter\n+   Run by git-cat-file or git-show when content is being pretty-printed\n+   for display to the user.  If no prettyfilter is set, then it should\n+   default to outfilter.\n+ - merge\n+   Git has built in, good support for merging standard text files.\n+   However, if you wanted to add an external merge tool for merging,\n+   say, XML files, you could supply it here\n+ - diff\n+   If you wanted to use an external diff for certain files, you would\n+   specify it in in the diff handler\n+\n+\n+\n+=== Filter list\n+\n+ - eol_lf\n+   Force all line endings to line-feed.\n+\n+ - eol_cr\n+   Force all line endings to carriage-return.\n+\n+ - eol_crlf\n+   Force all line endings to carriage-return, line-feed.\n+\n+ - eol_local\n+   Force all line endings to local default (LF on UNIX; CRLF on Windows).\n+\n+ - eol_auto\n+   Do the \"right thing\" depending on the file content and local default.\n+\n+ - pipe <cmd>\n+   Open a bidirectional pipe and run <cmd>; which will transform the\n+   file in whatever way one wishes.\n+\n+ - keywords\n+   The traditional CVS keywords are substituted in the file.  Maybe:\n+     $Id$, $Author$, $URL$, $Date$, $Rev$\n+   This filter would behave differently depending on whether it was an\n+   infilter or an outfilter.  On infilter it would remove the extra\n+   information.  On outfilter it would add the extra information.\n+\n+ - gunzip, gzip / zip, unzip\n+   Some files are stored compressed in their natural state (like ODF for\n+   example).  This isn't optimum for getting the best out of git.  Git\n+   (when making pack files) can store the delta between two files, and\n+   compresses all objects in its store anyway.  So, a compressed text\n+   file that changes over time will actually take up more disk space\n+   than the uncompressed file would take up.  These compression filters\n+   would fix that problem by transparently decompressing/compressing the\n+   files on their way in and out.\n+\n+\n+== Problems\n+\n+ - Initial Checkout\n+   The .gitattributes file is not in the working directory, so how git\n+   find out what to apply to a file?  The potential solution might be to\n+   use the in-repo .gitattributes for checking out; and the working-tree\n+   .gitattributes when checking in.\n+ - Merge of .gitattributes\n+   What happens when .gitattributes conflicts during a merge?\n+ - Change of .gitattributes without change of files.\n+   What happens when .gitattributes changes, but the files that would be\n+   affected by that change do not?  Those files really should be checked\n+   out again, to apply any new outfilter settings.\n-- \n1.5.0.2.205.g74e20\n"},{"id":"35981","messageId":"CF579EA9-04AB-4B39-809F-650E611A8D6B@silverinsanity.com","threadId":"7037","inReplyTo":"200703011206.47213.andyparkins@gmail.com","subject":"Re: [PATCH] Quick description of possible gitattributes system","fromName":"Brian Gernhardt","fromEmail":"benji@silverinsanity.com","sentAt":"2007-03-01T16:06:00Z","receivedAt":"2007-03-01T16:06:00Z","isPatch":true,"sender":{"key":"benji@silverinsanity.com","avatar":"https://gravatar.com/avatar/e06c101dbc25c68114d859b4a9ec7cf8a2c52fd2b0270ef0eac0e2e63ff22311?d=mp&s=160"},"body":"\nOn Mar 1, 2007, at 7:06 AM, Andy Parkins wrote:\n\n> The ideas in this document come primarily from the \"unresolved issues\"\n> thread from the git mailing list.  gmane/28388.  In particular, from:\n>  - Brian Gernhardt\n\nI still get a kick out of seeing my name mentioned on the list.  :-)   \nAnd if I'm getting some of the blame on me, (ew, get it off) I should  \nprobably put in my $0.02.\n\n> +   For example:\n> +\n> +   ------------------------------------\n> +   [attributes \"*.png\"]\n> +       attribute = image/png\n> +   [attributes \"*.c\"]\n> +       attribute = text/plain\n> +\t   attribute = source-file\n> +   ------------------------------------\n> +\n> +   (This is pretty ugly, because of the \"*\" and \".\" in the section  \n> name,\n> +   however I can't think of another way of doing this without  \n> resorting to\n> +   just copying the format of the .gitattributes file; like\n\nPerhaps:\n\n[attribute \"image/png\"]\n    path = *.png\n    show = \"open %path%\"\n[attribute \"text/plain\"]\n    path = *.c\n    checkout = eol_to_local\n\nI also think that this is a better way for handlers to be  \nspecified...  see below.\n\n> +== Handlers\n> +\n> +At this point git would be in a position to answer the question \"what\n> +attributes does this file have?\" for any file in the tree.\n> +\n> +The handler system will allow us to specify operations that should be\n> +performed on files with particular attributes.  For example, we might\n> +want to have text files automatically filtered to match local line\n> +ending conditions.\n> +\n> +----------------------------------------\n> +[handler \"fix-line-endings\"]\n> +  attribute = text/plain\n> +  infilter = eol_lf\n> +  outfilter = eol_local\n> +----------------------------------------\n> +\n> +This definition creates a handler named \"fix-line-endings\" (don't  \n> suppose\n> +they actually need names) that would run the \"eol_lf\" filter on check\n> +in, and the \"eol_local\" filter on checkout.\n> +\n\nI think it would be better to directly associated these with the  \nattribute, and have handler sections as shortcuts:\n\n[handler \"fix-line-endings\"]\n    infilter = eol_lf\n    outfilter = eol_local\n[attribute \"text/plain\"]\n    handler = fix-line-endings\n[attribute \"text/source\"]\n    patch = *.source\n    handler = fix-line-endings\n    infilter = prettypatch\n\nThe file type (attribute, whatever) is the more user-important thing  \nhere.  It should, therefore, be the most visible thing when editing.   \nI wouldn't want to have to read through the entirety of my config to  \nfind all of the handlers which affect a type, and it gathers all the  \noptions in one place.  Plus, it saves us from having to figure out in  \nwhat order multiple handler sections on the same attribute get run  \nin.  They get run in whatever order they're specified in the  \nattribute's section.\n\n> +=== Handler Types\n\n[snip]\n\n> +=== Filter list\n\n[snip]\n\nBoth of these lists look right at first glance, although I think I  \nprefer something simple like \"show\" to \"prettyfilter\".  And we might  \nwant a \"reject\" or \"none\" for merges...  Attempting to merge a bitmap  \nis madness, so the system should just output a <file>- \n<head>.<extension> or similar.\n\n> +== Problems\n> +\n> + - Initial Checkout\n> +   The .gitattributes file is not in the working directory, so how  \n> git\n> +   find out what to apply to a file?  The potential solution might  \n> be to\n> +   use the in-repo .gitattributes for checking out; and the  \n> working-tree\n> +   .gitattributes when checking in.\n> + - Merge of .gitattributes\n> +   What happens when .gitattributes conflicts during a merge?\n\nWe may have to special case .gitattributes.  Force a checkout of it  \nbefore any files in the directory or subdirectories, and not just on  \nthe initial checkout.  Checking out .gitattributes first during  \nmerges and pulls might be required and unmerged .gitattributes causes  \na big warning that it has to be resolved, and causes the rest of the  \nrepo to conform to the new attributes when it's resolved (possibly  \ncausing more merge conflicts).\n\n> + - Change of .gitattributes without change of files.\n> +   What happens when .gitattributes changes, but the files that  \n> would be\n> +   affected by that change do not?  Those files really should be  \n> checked\n> +   out again, to apply any new outfilter settings.\n\nActually, shouldn't the files also be run through the infilter to  \ncheck for changes caused by that, too?\n\nMaybe this is a more like a nickel,\n~~ Brian\n"},{"id":"35989","messageId":"200703011901.21474.robin.rosenberg.lists@dewire.com","threadId":"7037","inReplyTo":"200703011206.47213.andyparkins@gmail.com","subject":"Re: [PATCH] Quick description of possible gitattributes system","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg.lists@dewire.com","sentAt":"2007-03-01T18:01:20Z","receivedAt":"2007-03-01T18:01:20Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"torsdag 01 mars 2007 13:06 skrev Andy Parkins:\n> Junio was working on a gitattributes system.  Rather than be useful and\n> write code, I wrote this document to show how an attribute system might\n> work.\n> \n> The ideas in this document come primarily from the \"unresolved issues\"\n> thread from the git mailing list.  gmane/28388.  In particular, from:\n>  - Brian Gernhardt\n>  - Johannes Schindelin\n>  - Junio Hamano\n>  - Linus Torvalds\n>  - Martin Waitz\n>  - Nicolas Pitre\n>  - Robin Rosenberg\n>  - Theodore Tso\n> So they deserve the credit for the ideas, and I deserve the blame for\n> the description.\n> \n> Signed-off-by: Andy Parkins <andyparkins@gmail.com>\n> ---\n> This one is better.  I've included some of the points raised in the\n> \"unresolved issues\" thread from January.\n> \n>  Documentation/attributes.txt |  222 ++++++++++++++++++++++++++++++++++++++++++\n>  1 files changed, 222 insertions(+), 0 deletions(-)\n>  create mode 100644 Documentation/attributes.txt\n> \n> diff --git a/Documentation/attributes.txt b/Documentation/attributes.txt\n> new file mode 100644\n> index 0000000..9877786\n> --- /dev/null\n> +++ b/Documentation/attributes.txt\n> @@ -0,0 +1,222 @@\n> +Git Attributes System\n> +=====================\n> +\n> +This document is a work-in-progress.  It's only purpose is to assemble\n> +attribute ideas into one place.\n> +\n> +== Attributes\n> +\n> +Individual paths are assigned attributes.  Typically they will only have\n> +one attribute, typically named after the corresponding mime type of that\n> +file.  However, it is not required that the attribute be a mime type nor\n> +is it required that this be the only attribute.\n> +\n> +Attributes are attached to paths in one of two ways:\n> +\n> + - Via the .gitattributes file.  This will work in the same way as the\n> +   .gitignore file.  That is, there can be multiple .gitattributes files\n> +   throughout the working directory.\n> +\n> +   Typically the .gitattributes file will be a version controlled file,\n> +   just like .gitignore.\n> +\n> +   The format of this file will be similar to .gitignore.  \"#\" starting\n> +   a comment.  Globbing allowed.  Paths to subdirectories allowed.  Each\n> +   path will be followed by the list of attributes that applies to that\n> +   path.  Additionally, we would probably want a way of disabling an\n> +   attribute.  For example\n> +\n> +   -------------------------------------\n> +   # Sample .gitattributes file\n> +   *.png image/png\n> +   *.txt text/plain\n> +   *.c text/plain source-file\n> +   script/*.sh text/plain source-file\n> +   # Disable text/plain for a particular file\n> +   file-isnt-text-despite-extension.txt !text/plain\n> +   -------------------------------------\n> +\n> + - Via the git configuration file system.  i.e. /etc/gitconfig,\n> +   $HOME/.gitconfig and $GIT_DIR/config.\n> +\n> +   This supplies the same facility as the .gitattributes file but allows\n> +   the attributes to be specifed out-of-tree.  This will give the\n> +   advantage that standard attributes can be specified per-system via\n> +   /etc/gitconfig; per-user via $HOME/config or per-repository via\n> +   $GIT_DIR/config.\n> +\n> +   It will obviously be of different format from the .gitattributes\n> +   file, but the attribute names and path specification will be\n> +   identical (and specified as if from the root of the repository tree).\n> +   For example:\n> +\n> +   ------------------------------------\n> +   [attributes \"*.png\"]\n> +       attribute = image/png\n> +   [attributes \"*.c\"]\n> +       attribute = text/plain\n> +\t   attribute = source-file\n> +   ------------------------------------\n> +\n> +   (This is pretty ugly, because of the \"*\" and \".\" in the section name,\n> +   however I can't think of another way of doing this without resorting to\n> +   just copying the format of the .gitattributes file; like\n> +   -------------------------------------\n> +   [attributes]\n> +       path = *.png image/png\n> +\t   path = *.txt text/plain\n> +\t   path = *.c text/plain source-file\n> +   -------------------------------------\n> +   but perhaps people would like that more?)\n> +\n> +With these two in place, attributes for files can be specified and\n> +overridden easily.  The priority of the various files will be (from\n> +lowest to highest)\n> +\n> + - /etc/gitconfig\n> + - $HOME/.gitconfig\n> + - .gitattributes\n> + - $GIT_DIR/config\n> +\n> +The $GIT_DIR/config file is highest priority so that a user can always\n> +override an attribute that is in a .gitattributes managed by someone\n> +else.\n> +\n> +\n> +== Handlers\n> +\n> +At this point git would be in a position to answer the question \"what\n> +attributes does this file have?\" for any file in the tree.\n> +\n> +The handler system will allow us to specify operations that should be\n> +performed on files with particular attributes.  For example, we might\n> +want to have text files automatically filtered to match local line\n> +ending conditions.\n> +\n> +----------------------------------------\n> +[handler \"fix-line-endings\"]\n> +  attribute = text/plain\n> +  infilter = eol_lf\n> +  outfilter = eol_local\n> +----------------------------------------\n> +\n> +This definition creates a handler named \"fix-line-endings\" (don't suppose\n> +they actually need names) that would run the \"eol_lf\" filter on check\n> +in, and the \"eol_local\" filter on checkout.\n> +\n> +Similarly, we might want to tell git-show how to show images:\n> +\n> +----------------------------------------\n> +[handler \"show-images\"]\n> +  attribute = image/png\n> +  attribute = image/jpeg\n> +  attribute = image/gif\n> +  prettyfilter = pipe display -\n> +----------------------------------------\n> +\n> +With this filter in place,\n> +----------------------------------------\n> + $ git-show v1.0.0:images/picture.png\n> +----------------------------------------\n> +Would run \"display -\" and pipe the picture to it.\n> +\n> +Multiple filters can be supplied, and order will be important.  So, to\n> +transparently decompress a file and fix the line endings for a text file\n> +we might do:\n> +\n> +---------------------------------------\n> +[handler \"decompress-text\"]\n> +  attribute = compressed-text\n> +  infilter = gunzip\n> +  infilter = eol_lf\n> +  outfilter = eol_local\n> +  outfilter = gzip\n> +---------------------------------------\n> +\n> +This might be useful for documentation files that come compressed (like\n> +README.gz used by Debian).\n> +\n> +Similarly, we might want to be able to look at compressed files stored\n> +in the repository:\n> +\n> +---------------------------------------\n> +[handler \"show-compressed-file\"]\n> +  attribute = application/gzip\n> +  prettyfilter = gunzip\n> +  prettyfilter = eol_auto\n> +---------------------------------------\n> +\n> +=== Handler Types\n> +\n> + - infilter\n> +   Run by git-add when content is added to the repository.\n> + - outfilter\n> +   Run by git-checkout or git-reset when copying content from the index\n> +   to the working directory.  (Actually, more likely this would be done\n> +   at low level in git-read-tree)\n> + - prettyfilter\n> +   Run by git-cat-file or git-show when content is being pretty-printed\n> +   for display to the user.  If no prettyfilter is set, then it should\n> +   default to outfilter.\n> + - merge\n> +   Git has built in, good support for merging standard text files.\n> +   However, if you wanted to add an external merge tool for merging,\n> +   say, XML files, you could supply it here\n> + - diff\n> +   If you wanted to use an external diff for certain files, you would\n> +   specify it in in the diff handler\n> +\n> +\n> +\n> +=== Filter list\n> +\n> + - eol_lf\n> +   Force all line endings to line-feed.\n> +\n> + - eol_cr\n> +   Force all line endings to carriage-return.\n> +\n> + - eol_crlf\n> +   Force all line endings to carriage-return, line-feed.\n> +\n> + - eol_local\n> +   Force all line endings to local default (LF on UNIX; CRLF on Windows).\n> +\n> + - eol_auto\n> +   Do the \"right thing\" depending on the file content and local default.\n> +\n> + - pipe <cmd>\n> +   Open a bidirectional pipe and run <cmd>; which will transform the\n> +   file in whatever way one wishes.\n> +\n> + - keywords\n> +   The traditional CVS keywords are substituted in the file.  Maybe:\n> +     $Id$, $Author$, $URL$, $Date$, $Rev$\n> +   This filter would behave differently depending on whether it was an\n> +   infilter or an outfilter.  On infilter it would remove the extra\n> +   information.  On outfilter it would add the extra information.\n> +\n> + - gunzip, gzip / zip, unzip\n> +   Some files are stored compressed in their natural state (like ODF for\n> +   example).  This isn't optimum for getting the best out of git.  Git\n> +   (when making pack files) can store the delta between two files, and\n> +   compresses all objects in its store anyway.  So, a compressed text\n> +   file that changes over time will actually take up more disk space\n> +   than the uncompressed file would take up.  These compression filters\n> +   would fix that problem by transparently decompressing/compressing the\n> +   files on their way in and out.\nA good option to have, but not a default. A problem with zip is ofcourse that it represent many files. \nPresumably \n> +\n> +\n> +== Problems\n> +\n> + - Initial Checkout\n> +   The .gitattributes file is not in the working directory, so how git\n> +   find out what to apply to a file?  The potential solution might be to\n> +   use the in-repo .gitattributes for checking out; and the working-tree\n> +   .gitattributes when checking in.\nGit can read the file from the tree it is about to check out. On check in it should read\nthe version in the index for consitency. That still leaves the problem of which file\nto check when updating the index. Should the index be recomputed when the copy\nof the file in the index gets updated? Probably. The .gitattributes must be the first file\nin each tree to check in order to make all other blobs consistent with it.\n\n> + - Merge of .gitattributes\nSince they are text files it shold be possible to merge, but is the format \"merge friendly\", i.e.\nunlikely to cause conflicts and  most importantly unlikely to cause incorrect merges. The\nfile is not likely to be updated very often. Maybe the first case for special merge programs?\n\n> +   What happens when .gitattributes conflicts during a merge?\nOuch, ... need more thinking \n\n> + - Change of .gitattributes without change of files.\nRecompute index, and possible change of files in git (.e.g files with CRLF get normalized\nto LF is that is the change indicated by .gitattributes).\n\n> +   What happens when .gitattributes changes, but the files that would be\n> +   affected by that change do not?  Those files really should be checked\n> +   out again, to apply any new outfilter settings.\n\nOnly on git-reset/checkout.\n\n-- robin\n"},{"id":"36034","messageId":"7vejo8o69o.fsf@assigned-by-dhcp.cox.net","threadId":"7037","inReplyTo":"200703011206.47213.andyparkins@gmail.com","subject":"Re: [PATCH] Quick description of possible gitattributes system","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-03-02T00:09:39Z","receivedAt":"2007-03-02T00:09:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Andy Parkins <andyparkins@gmail.com> writes:\n\n> +Attributes are attached to paths in one of two ways:\n> +\n> + - Via the .gitattributes file.  This will work in the same way as the\n> +   .gitignore file.  That is, there can be multiple .gitattributes files\n> +   throughout the working directory.\n> +\n> +   Typically the .gitattributes file will be a version controlled file,\n> +   just like .gitignore.\n\nAnother point to stress here is that these are property of the\npaths of the project and independent of the platform each user\nhappens to have a repository of the project on.  If something is\ntext, then it is text whether the platform is on UNIX or on DOS.\n\n> +   It will obviously be of different format from the .gitattributes\n> +   file, but the attribute names and path specification will be\n> +   identical (and specified as if from the root of the repository tree).\n\nI am in favor of also using $GIT_DIR/config format even for the\nin-tree .gitattributes files.  For one thing, it makes the\nsyntax and quoting rules saner and more consistent (blanks in\npathname patterns and such), and we already have a parser for\nit.\n\n\t[attribute \"image/png\"]\n        \tpath = \"*.png\"\n\n\t[attribute \"image/jpg\"]\n        \tpath = \"*.jpg\"\n        \tpath = \"*.jpeg\"\n\n\t[attribute \"text\"]\n\t\t; anything that is image/* is non-text -- I am\n                ; not sure if we want to allow this which means\n                ; we need to resolve dependencies, though.\n                attr = \"!image/*\"\n\t\t; inside list of path-patterns, the first match wins.\n\t\tpath = \"!this-is-not-text.txt\"\n        \tpath = \"*\"\n\n\t; .gitignore is a mere special case of \"ignored\" attribute.\n\t[attribute \"ignored\"]\n        \tpath = \"*~\"\n                path = \"!hand-maintained.o\"\n                path = \"*.[aso]\"\n\nEarlier, I said attributes are property of project, but that\ndoes not mean we should forbid users to define more paths in\nconfig.  On DOS, you might want to have:\n\n\t[attribute \"ignored\"]\n        \tpath = \"*.obj\"\n\nto suppliment the last entry of the above \"ignored\" that is\nmeant to catch object files, until the upstream project adds it\nto the .gitattribute files.\n\nIn contrast to that attributes define property of paths of the\nproject, handlers define how we should behave on paths with\ncertain attributes in a particular repository.  So it is\nimportant to stress that that handler sections should never\nappear in in-tree .gitattributes files.  Because they are\nper-repository, the same project checked out on DOS will be used\nwith this handler definition (which would be the built-in\ndefault not to require the users to have one in ~/.gitconfig):\n\n\t[handler \"text\"]\n        \tinput = crlf\n                output = crlf\n\nwhile on UNIX the input/output would be no-op.\n\n> +----------------------------------------\n> +[handler \"fix-line-endings\"]\n> +  attribute = text/plain\n> +  infilter = eol_lf\n> +  outfilter = eol_local\n> +----------------------------------------\n> +\n> +This definition creates a handler named \"fix-line-endings\" (don't suppose\n> +they actually need names) that would run the \"eol_lf\" filter on check\n> +in, and the \"eol_local\" filter on checkout.\n\nI would suggest making handler section _match_ the attribute\nnames.  By \"match\", what I mean is to allow something like this:\n\n\t[handler \"image/*\"]\n        \tpretty = \"cmd display -\"\n\neven though the attributes are \"image/png\", \"image/jpg\", etc.\n\n> +[handler \"show-images\"]\n> +  attribute = image/gif\n> +  prettyfilter = pipe display -\n\nI would recommend against calling them *filter.  After all, the\nsemantics of each handler action (such as input, output and\npretty) already determine if it needs to act as a filter or data\nsink.  We do not need to say prettyfilter either; it is not even\na filter to begin with -- it is a data sink.\n"},{"id":"36038","messageId":"7vps7smevd.fsf@assigned-by-dhcp.cox.net","threadId":"7037","inReplyTo":"7vejo8o69o.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Quick description of possible gitattributes system","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-03-02T04:46:46Z","receivedAt":"2007-03-02T04:46:46Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <junkio@cox.net> writes:\n\n> I am in favor of also using $GIT_DIR/config format even for the\n> in-tree .gitattributes files.\n\nThinking about this a bit more, I take this \"syntax\" part back.\nOne-line-per-record format is much nicer if we want to keep this\ninformation in .gitattributes files in-tree, especially because\nthe changes to them _could_ conflict, and the pathattr mechanism\nneeds to work with such a file left in the working tree as its\ninput.  I suspect the config parser would simply say \"oops\" and\ndie given a malformed input resulting from conflict markers.  It\nis easy to ignore <<< === >>> lines and we would get a sensible\nresult.\n\nWhich automatically means that there will be no \"continuation\nlines\".\n"},{"id":"36076","messageId":"200703020856.35246.andyparkins@gmail.com","threadId":"7037","inReplyTo":"7vejo8o69o.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Quick description of possible gitattributes system","fromName":"Andy Parkins","fromEmail":"andyparkins@gmail.com","sentAt":"2007-03-02T08:56:31Z","receivedAt":"2007-03-02T08:56:31Z","isPatch":true,"sender":{"key":"andyparkins@gmail.com","avatar":null},"body":"On Friday 2007 March 02 00:09, Junio C Hamano wrote:\n\n[deleted lots of easily-agreed-with stuff]\n\n> I would suggest making handler section _match_ the attribute\n> names.  By \"match\", what I mean is to allow something like this:\n\nI don't see that working.  If it were possible to do that why would we need \nseparate handlers and attributes?  You're example is fine\n\n> \t[handler \"image/*\"]\n>         \tpretty = \"cmd display -\"\n\nBut what about when I want to do this:\n\n[handler \"lossless-images-only\"]\n   attribute = \"image/png\"\n   attribute = \"image/gif\"\n   pre-commit = /bin/false\n\nTo prevent the adding of all lossless image formats?  I actually can't see a \ntime when the handler name needs referencing, so it can be anything (as long \nas it's unique - perhaps).  If you wanted to use/encourage the attribute \nname - fine, but it shouldn't be required.  However I think it's more \nsensible to name the handler after what it does than what it applies to - the \napplies to can change, what it does never.\n\nThe handlers are like function calls.  You wouldn't want to name functions \nafter where they were called.\n\n> > +[handler \"show-images\"]\n> > +  attribute = image/gif\n> > +  prettyfilter = pipe display -\n>\n> I would recommend against calling them *filter.  After all, the\n> semantics of each handler action (such as input, output and\n> pretty) already determine if it needs to act as a filter or data\n> sink.  We do not need to say prettyfilter either; it is not even\n> a filter to begin with -- it is a data sink.\n\nThat's true; I don't have any strong feelings.  I just didn't like \"convert\" \nbeing used.  Convert always sounds like something that takes one thing and \nmakes another out of it - at the end you have two things.  Filters transform \none thing into another - at the end you have one thing.\n\nPerhaps better names would be simply to name them after the operation the runs \nthem.\n\n infilter = checkin\n outfilter = checkout\n prettyfilter = show\n\n?\n\nIs the document useful; would you like me to maintain it?  I don't want to \nwaste your time with it.\n\n\nAndy\n-- \nDr Andy Parkins, M Eng (hons), MIET\nandyparkins@gmail.com\n"},{"id":"36077","messageId":"200703020858.58741.andyparkins@gmail.com","threadId":"7037","inReplyTo":"7vps7smevd.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Quick description of possible gitattributes system","fromName":"Andy Parkins","fromEmail":"andyparkins@gmail.com","sentAt":"2007-03-02T08:58:54Z","receivedAt":"2007-03-02T08:58:54Z","isPatch":true,"sender":{"key":"andyparkins@gmail.com","avatar":null},"body":"On Friday 2007 March 02 04:46, Junio C Hamano wrote:\n\n> Thinking about this a bit more, I take this \"syntax\" part back.\n> One-line-per-record format is much nicer if we want to keep this\n> information in .gitattributes files in-tree, especially because\n\nThat was my original thought.  However, it occurred to me that we might have \nan implicit handler for .gitattributes that said\n\n[handler \"attributesfile\"]\n  merge = builtin-attributes-merge\n\nSo you don't necessarily have to keep it line based (although I suppose that \nis easier than writing a special merger).\n\n\nAndy\n-- \nDr Andy Parkins, M Eng (hons), MIET\nandyparkins@gmail.com\n"},{"id":"36079","messageId":"200703021200.35069.andyparkins@gmail.com","threadId":"7037","inReplyTo":"CF579EA9-04AB-4B39-809F-650E611A8D6B@silverinsanity.com","subject":"Re: [PATCH] Quick description of possible gitattributes system","fromName":"Andy Parkins","fromEmail":"andyparkins@gmail.com","sentAt":"2007-03-02T12:00:34Z","receivedAt":"2007-03-02T12:00:34Z","isPatch":true,"sender":{"key":"andyparkins@gmail.com","avatar":null},"body":"On Thursday 2007, March 01, Brian Gernhardt wrote:\n\n> [attribute \"image/png\"]\n>     path = *.png\n>     show = \"open %path%\"\n> [attribute \"text/plain\"]\n>     path = *.c\n>     checkout = eol_to_local\n\nThe problem is that this flips the relationship.  What you want to do is \nassign attributes to paths.  This is assigning paths to attributes.  \nWhat about this:\n\n  doc/*.txt = text/plain AND documentation\n\nIn your system that would make\n\n[attribute text/plain]\n  path = doc/*.txt\n  show = \"open %path%\"\n[attribute documentation]\n  path = doc/*.txt\n  show = \"open %path\"\n\ni.e. you've got two sections to maintain instead of one.  That's why I \nsuggested:\n\n[attributes \"doc/*.txt\"]\n  attributes = text/plain\n  attributes = documentation\n\nI'm not really advocating that exact syntax, but I do think it's got to \nbe like having a database like this:\n\n  paths -> path-attribute-join <- attributes\n  attributes -> handlers\n\nYour method does\n  path -> attribute\n  attribute -> handlers\n\nThere would therefore be excessive repetition or impossible-to-specify \nconnections.\n\n\n> Both of these lists look right at first glance, although I think I\n> prefer something simple like \"show\" to \"prettyfilter\".  And we might\n> want a \"reject\" or \"none\" for merges...  Attempting to merge a bitmap\n> is madness, so the system should just output a <file>-\n> <head>.<extension> or similar.\n\nI have no major concerns about any of the syntax really.  The important thing \nis that we are clear and consistent (as always).\n\n\n> > + - Change of .gitattributes without change of files.\n> > +   What happens when .gitattributes changes, but the files that\n> > would be\n> > +   affected by that change do not?  Those files really should be\n> > checked\n> > +   out again, to apply any new outfilter settings.\n>\n> Actually, shouldn't the files also be run through the infilter to\n> check for changes caused by that, too?\n\nI don't think so.  The effect of the infilter will never be seen in the \nworking tree, because it's applied on git-add.  The previous content with the \nold attributes are already in the repository.  However, it could be that we \nwould have to force those files to be marked dirty in the index (this is \nalready sounding bad), to force the application of the infilter on next \ncheckin.  Perhaps that's what you meant, and I'm being slow.\n\n\nAndy\n-- \nDr Andy Parkins, M Eng (hons), MIET\nandyparkins@gmail.com\n"},{"id":"36086","messageId":"es9aal$5gf$1@sea.gmane.org","threadId":"7037","inReplyTo":"200703011206.47213.andyparkins@gmail.com","subject":"Re: [PATCH] Quick description of possible gitattributes system","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-03-02T13:56:49Z","receivedAt":"2007-03-02T13:56:49Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Andy Parkins wrote:\n\n> + - prettyfilter\n> +   Run by git-cat-file or git-show when content is being pretty-printed\n> +   for display to the user.  If no prettyfilter is set, then it should\n> +   default to outfilter.\n\nI'd rather have plumbing operate without filters (if it is possible),\nso git-cat-file would not run prettyfilter, and git-show would run it.\n\nOr at least detect if output is tty, so one can do something like\n\"git cat-file -p v1.0.0:gitweb/git-logo.png > git-logo.png\" and get\nexpected result, while \"git show v1.0.0:gitweb/git-logo.png\" would\nshow the image.\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"36110","messageId":"Pine.LNX.4.64.0703020850470.3953@woody.linux-foundation.org","threadId":"7037","inReplyTo":"es9aal$5gf$1@sea.gmane.org","subject":"Re: [PATCH] Quick description of possible gitattributes system","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-03-02T16:58:24Z","receivedAt":"2007-03-02T16:58:24Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 2 Mar 2007, Jakub Narebski wrote:\n\n> Andy Parkins wrote:\n> \n> > + - prettyfilter\n> > +   Run by git-cat-file or git-show when content is being pretty-printed\n> > +   for display to the user.  If no prettyfilter is set, then it should\n> > +   default to outfilter.\n> \n> I'd rather have plumbing operate without filters (if it is possible),\n> so git-cat-file would not run prettyfilter, and git-show would run it.\n\nThat really sucks. I do \"git show xyz > filname\" all the time, and while \nit's been about diffs and commits, I could imagine doing the same thing \nfor things like \"git show v2.6.17:Documentation/logo.gif > some.gif\" too.\n\nYes, I know could do \"git cat-file -p ..\" instead, but since we added \"git \nshow\", and made it do the Right Thing (tm) for blobs, I've come to use it \nmore (which is as it should be: \"cat-file\" is low-level plumbing, while \n\"git show\" is what you'd expect users to use.\n\nSo I really think that the issue here is that the *pager* should do the \nright thing. Which gets us to:\n\n> Or at least detect if output is tty, so one can do something like\n> \"git cat-file -p v1.0.0:gitweb/git-logo.png > git-logo.png\" and get\n> expected result, while \"git show v1.0.0:gitweb/git-logo.png\" would\n> show the image.\n\nYes. How about just having the built-in git pager do the right thing?\n\nRight now we actually wait for data to start arriving (commit 35ce862) due \nto working around a bug in less. But what if we could make the pager \nactually do the right thing here automatically? With \"less\" just being the \ndefault action for *text*?\n\n\t\t\tLinus"},{"id":"36111","messageId":"E246B7BC-9C82-4F4E-93F0-60B3F1CA54F1@silverinsanity.com","threadId":"7037","inReplyTo":"200703021200.35069.andyparkins@gmail.com","subject":"Re: [PATCH] Quick description of possible gitattributes system","fromName":"Brian Gernhardt","fromEmail":"benji@silverinsanity.com","sentAt":"2007-03-02T18:05:06Z","receivedAt":"2007-03-02T18:05:06Z","isPatch":true,"sender":{"key":"benji@silverinsanity.com","avatar":"https://gravatar.com/avatar/e06c101dbc25c68114d859b4a9ec7cf8a2c52fd2b0270ef0eac0e2e63ff22311?d=mp&s=160"},"body":"\nOn Mar 2, 2007, at 7:00 AM, Andy Parkins wrote:\n\n> On Thursday 2007, March 01, Brian Gernhardt wrote:\n>\n>> [attribute \"image/png\"]\n>>     path = *.png\n>>     show = \"open %path%\"\n>> [attribute \"text/plain\"]\n>>     path = *.c\n>>     checkout = eol_to_local\n>\n> The problem is that this flips the relationship.  What you want to  \n> do is\n> assign attributes to paths.  This is assigning paths to attributes.\n> What about this:\n>\n>   doc/*.txt = text/plain AND documentation\n>\n> In your system that would make\n\nI'm sorry, I was assuming that information on what to do with each  \nattribute would be in the config file while a majority of the  \nattribute information was in an in-tree file.  I was actually assuming:\n\n.gitattributes:\n*.png: image/png\nlogo.png: logo\n*.c: text/plain source\n\n.git/config:\n[attribute \"image\"]\n    show = ...\n    merge = ...\n\nWith the ability to have additional \"path =\" entries for *local*  \noverrides/additions.  Storing the handler information in  \nthe .gitattributes is one of the worst things you could do, IMHO.  It  \nassumes that people will have a homogenous environment to develop in,  \nand that every developer want to use the same tools.  In some cases,  \nthis may be true (eol_lf on checking for everybody), but not in  \nothers.  On my Mac, I'd like to use \"open\" for random file types, and  \nmight want to use VERY different graphical merge than Linux users.   \nAnd OS X is a fairly Unix-like environment.  Let's not even ponder  \nthose poor fools using MinGW.  ;-)\n\n>> Actually, shouldn't the files also be run through the infilter to\n>> check for changes caused by that, too?\n>\n> I don't think so.  The effect of the infilter will never be seen in  \n> the\n> working tree, because it's applied on git-add.  The previous  \n> content with the\n> old attributes are already in the repository.  However, it could be  \n> that we\n> would have to force those files to be marked dirty in the index  \n> (this is\n> already sounding bad), to force the application of the infilter on  \n> next\n> checkin.  Perhaps that's what you meant, and I'm being slow.\n\nThat's something like what I meant.  And it sounds bad.  Content  \nchanges caused by attribute changes should likely be handled by the  \nuser and made easy to detect instead of trying to handle it  \nautomatically.  So ignore my original statement on the matter.\n\n~~ Brian\n"},{"id":"36120","messageId":"200703021935.58992.andyparkins@gmail.com","threadId":"7037","inReplyTo":"E246B7BC-9C82-4F4E-93F0-60B3F1CA54F1@silverinsanity.com","subject":"Re: [PATCH] Quick description of possible gitattributes system","fromName":"Andy Parkins","fromEmail":"andyparkins@gmail.com","sentAt":"2007-03-02T19:35:57Z","receivedAt":"2007-03-02T19:35:57Z","isPatch":true,"sender":{"key":"andyparkins@gmail.com","avatar":null},"body":"On Friday 2007, March 02, Brian Gernhardt wrote:\n\n> I'm sorry, I was assuming that information on what to do with each\n> attribute would be in the config file while a majority of the\n> attribute information was in an in-tree file.  I was actually\n> assuming:\n\nIt's definitely in the .gitattributes file, but is also optionally in \nthe config as well.  This means that a user can always override \nsomething locally - i.e. they're always in control of their own \nrepository, even when they disagree with upstream (perhaps).\n\n> .git/config:\n> [attribute \"image\"]\n>     show = ...\n>     merge = ...\n>\n> With the ability to have additional \"path =\" entries for *local*\n> overrides/additions.  Storing the handler information in\n\nThat's almost exactly it; but it makes the assumption that each \nattribute will have one unique handler.  Separating them means that \nmultiple attributes can use one handler (or set of handlers).\n\n> the .gitattributes is one of the worst things you could do, IMHO.  It\n> assumes that people will have a homogenous environment to develop in,\n\nOh definitely.  This is one thing that everybody absolutely agrees on.  \nThe in-tree file /only/ adds attributes and never says what effect \nthose attributes have.\n\n\n\nAndy\n\n-- \nDr Andy Parkins, M Eng (hons), MIET\nandyparkins@gmail.com\n"},{"id":"36121","messageId":"200703021937.33648.andyparkins@gmail.com","threadId":"7037","inReplyTo":"Pine.LNX.4.64.0703020850470.3953@woody.linux-foundation.org","subject":"Re: [PATCH] Quick description of possible gitattributes system","fromName":"Andy Parkins","fromEmail":"andyparkins@gmail.com","sentAt":"2007-03-02T19:37:31Z","receivedAt":"2007-03-02T19:37:31Z","isPatch":true,"sender":{"key":"andyparkins@gmail.com","avatar":null},"body":"On Friday 2007, March 02, Linus Torvalds wrote:\n\n> Yes. How about just having the built-in git pager do the right thing?\n\nPerfect.  This is absolutely the right thing to do I think.\n\n\nAndy\n-- \nDr Andy Parkins, M Eng (hons), MIET\nandyparkins@gmail.com\n"},{"id":"36123","messageId":"8CAB85E5-A98E-4A25-9CC2-3E59106E655C@silverinsanity.com","threadId":"7037","inReplyTo":"200703021935.58992.andyparkins@gmail.com","subject":"Re: [PATCH] Quick description of possible gitattributes system","fromName":"Brian Gernhardt","fromEmail":"benji@silverinsanity.com","sentAt":"2007-03-02T20:35:16Z","receivedAt":"2007-03-02T20:35:16Z","isPatch":true,"sender":{"key":"benji@silverinsanity.com","avatar":"https://gravatar.com/avatar/e06c101dbc25c68114d859b4a9ec7cf8a2c52fd2b0270ef0eac0e2e63ff22311?d=mp&s=160"},"body":"\nOn Mar 2, 2007, at 2:35 PM, Andy Parkins wrote:\n\n>> .git/config:\n>> [attribute \"image\"]\n>>     show = ...\n>>     merge = ...\n>>\n>> With the ability to have additional \"path =\" entries for *local*\n>> overrides/additions.  Storing the handler information in\n>\n> That's almost exactly it; but it makes the assumption that each\n> attribute will have one unique handler.  Separating them means that\n> multiple attributes can use one handler (or set of handlers).\n\nThat's why I suggested keeping the handler section, but not tying  \nhandlers to attributes in the attribute section.  I think it follows  \nthe principle of least surprise to be able to do as I demonstrated  \nabove, but allow reuse as I described originally (handler option in  \nthe attribute section).  My major concern is how do you tell what  \norder handlers are run in for a given file if the handlers specify  \nthe attributes rather than the other way around?  And why make the  \nuser do things like:\n\n[handler \"text\"]\n    attribute=text\n    ...\n\nInstead of:\n\n[attribute \"text\"]\n    ...\n\n(The handler section could be called \"mangle\", \"blah\", or \"why-do-I- \nhave-to-name-this\", and the point would be the same.)  If you want to  \nrun the same handlers/filters/whatever for multiple types, create a  \nhandler section and reference it from all of those types or give all  \nthe files a new attribute that explains why you'd want to handle them  \nidentically and put the options on that attribute instead.\n\nThe attribute is the important thing here, not the handlers, so they  \nshould be primary, not secondary.  And that's my major point that I'm  \ntrying to get around to I guess.  I don't care about naming handler  \nsections, searching through the file to find their order, or anything  \nother than *what git is doing to my files*.  The files (content,  \nactually) are king.\n\n~~ Brian\n"},{"id":"36127","messageId":"Pine.LNX.4.64.0703021249010.3953@woody.linux-foundation.org","threadId":"7037","inReplyTo":"200703021937.33648.andyparkins@gmail.com","subject":"Re: [PATCH] Quick description of possible gitattributes system","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-03-02T21:02:23Z","receivedAt":"2007-03-02T21:02:23Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 2 Mar 2007, Andy Parkins wrote:\n\n> On Friday 2007, March 02, Linus Torvalds wrote:\n> \n> > Yes. How about just having the built-in git pager do the right thing?\n> \n> Perfect.  This is absolutely the right thing to do I think.\n\nWell, it would be perfect, except it's rather hard to do. Right now we \nsimply don't have any way to tell the pager what to do with the data, and \nwe'd need to do some communications passing thing to let it know.\n\nIt *could* just look at the data directly, but that's actually hard: if we \nstart looking at the data, there's no way to push the data back onto the \nhead of a pipe, and there's no really good way to tell an external pager \nto \"start off with this data that I already read earlier to figure out the \ntype, and then continue with that other file descriptor that I'm passing \nin\".\n\nSo then we'd have to have a totally useless process in between the git \nprocess and the external pager to just feed the data from one pipe to the \nother..\n\nDoing the pager internally would obviously solve that issue, but I really \ndon't think we want to do that, especially since it's very \nsystem-dependent. And temporary files suck for all the other reasons \n(incrementally generated data).\n\nSo we're in the situation where:\n\n - the pager process *will* wait until actual data is starting to appear,\n   so we *can* have some side-band channel to tell it \"oh, btw, if there \n   is a pager, this is going to be image data, so start up an external \n   image viewer instead\". \n\n - but I don't have a good clue what side-band to use. We could use \n   a special \"FILE *pagerdata\", of course (which would just be fd#3 in \n   the pager). Then, \"git show\" could just do something like\n\n\tif (pager_in_use)\n\t\tfprintf(pagerdata, \"'%s'\\n\", type);\n\n   and we could change pager.c to do something like the appended patch.\n\nbut I have to say, it looks a bit strange.\n\n\t\tLinus\n\n---\ndiff --git a/pager.c b/pager.c\nindex 5f280ab..b71dd44 100644\n--- a/pager.c\n+++ b/pager.c\n@@ -9,6 +9,8 @@\n \n static void run_pager(const char *pager)\n {\n+\tstatic char input_type[100] = \"text\";\n+\n \t/*\n \t * Work around bug in \"less\" by not starting it until we\n \t * have real input\n@@ -17,7 +19,16 @@ static void run_pager(const char *pager)\n \n \tFD_ZERO(&in);\n \tFD_SET(0, &in);\n-\tselect(1, &in, NULL, &in, NULL);\n+\tFD_SET(3, &in);\n+\tselect(4, &in, NULL, &in, NULL);\n+\tif (FS_ISSET(3, &in)) {\n+\t\tint n = read(3, input_type, sizeof(input_type)-1);\n+\t\tif (n > 0)\n+\t\t\tinput_type[n] = 0;\n+\t}\n+\tclose(3);\n+\n+\tpager = select_pager(input_type, pager);\n \n \texeclp(pager, pager, NULL);\n \texecl(\"/bin/sh\", \"sh\", \"-c\", pager, NULL);\n"},{"id":"36130","messageId":"Pine.LNX.4.63.0703022237000.22628@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"7037","inReplyTo":"Pine.LNX.4.64.0703021249010.3953@woody.linux-foundation.org","subject":"Re: [PATCH] Quick description of possible gitattributes system","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-03-02T21:45:10Z","receivedAt":"2007-03-02T21:45:10Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 2 Mar 2007, Linus Torvalds wrote:\n\n> Doing the pager internally would obviously solve that issue,\n\nOoooooh! A builtin! (Seriously, I thought about that already, but \ndismissed it for the reasons you said, and more...)\n\n> So we're in the situation where:\n> \n>  - the pager process *will* wait until actual data is starting to appear,\n>    so we *can* have some side-band channel to tell it \"oh, btw, if there \n>    is a pager, this is going to be image data, so start up an external \n>    image viewer instead\". \n> \n>  - but I don't have a good clue what side-band to use. We could use \n>    a special \"FILE *pagerdata\", of course (which would just be fd#3 in \n>    the pager). Then, \"git show\" could just do something like\n> \n> \tif (pager_in_use)\n> \t\tfprintf(pagerdata, \"'%s'\\n\", type);\n> \n>    and we could change pager.c to do something like the appended patch.\n> \n> but I have to say, it looks a bit strange.\n\nThe obvious thing, of course, is a git-show specific solution (this is no \npatch, it only illustrates my idea):\n\n builtin-log.c |   11 +++++++++++\n git.c         |    2 +-\n 2 files changed, 12 insertions(+), 1 deletions(-)\n\ndiff --git a/builtin-log.c b/builtin-log.c\nindex 1c9f7d0..83e6cea 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -123,6 +123,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)\n \tstruct rev_info rev;\n \tstruct object_array_entry *objects;\n \tint i, count, ret = 0;\n+\tenum { NO_PAGER, TEXT_PAGER, OTHER_PAGER } pager_mode = NO_PAGER;\n \n \tgit_config(git_log_config);\n \tinit_revisions(&rev, prefix);\n@@ -140,6 +141,16 @@ int cmd_show(int argc, const char **argv, const char *prefix)\n \tfor (i = 0; i < count && !ret; i++) {\n \t\tstruct object *o = objects[i].item;\n \t\tconst char *name = objects[i].name;\n+\t\tif (o->type == OBJ_BLOB) {\n+\t\t\t/* determine if name falls into some special class */\n+\t\t\tif (pager_mode == NO_PAGER &&\n+\t\t\t\t\tsetup_special_pager(name))\n+\t\t\t\tpager_mode = OTHER_PAGER;\n+\t\t}\n+\t\tif (pager_mode == NO_PAGER) {\n+\t\t\tsetup_pager();\n+\t\t\tpager_mode = TEXT_PAGER;\n+\t\t}\n \t\tswitch (o->type) {\n \t\tcase OBJ_BLOB:\n \t\t\tret = show_object(o->sha1, 0);\ndiff --git a/git.c b/git.c\nindex 909adf2..a3811e6 100644\n--- a/git.c\n+++ b/git.c\n@@ -291,7 +291,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)\n \t\t{ \"runstatus\", cmd_runstatus, RUN_SETUP | DISALLOW_IN_GIT_DIR },\n \t\t{ \"shortlog\", cmd_shortlog, RUN_SETUP | USE_PAGER },\n \t\t{ \"show-branch\", cmd_show_branch, RUN_SETUP },\n-\t\t{ \"show\", cmd_show, RUN_SETUP | USE_PAGER },\n+\t\t{ \"show\", cmd_show, RUN_SETUP },\n \t\t{ \"stripspace\", cmd_stripspace },\n \t\t{ \"symbolic-ref\", cmd_symbolic_ref, RUN_SETUP },\n \t\t{ \"tar-tree\", cmd_tar_tree },\n"},{"id":"36134","messageId":"200703022221.38309.andyparkins@gmail.com","threadId":"7037","inReplyTo":"Pine.LNX.4.64.0703021249010.3953@woody.linux-foundation.org","subject":"Re: [PATCH] Quick description of possible gitattributes system","fromName":"Andy Parkins","fromEmail":"andyparkins@gmail.com","sentAt":"2007-03-02T22:21:30Z","receivedAt":"2007-03-02T22:21:30Z","isPatch":true,"sender":{"key":"andyparkins@gmail.com","avatar":null},"body":"On Friday 2007, March 02, Linus Torvalds wrote:\n> On Fri, 2 Mar 2007, Andy Parkins wrote:\n> > On Friday 2007, March 02, Linus Torvalds wrote:\n> > > Yes. How about just having the built-in git pager do the right\n> > > thing?\n> >\n> > Perfect.  This is absolutely the right thing to do I think.\n>\n> Well, it would be perfect, except it's rather hard to do. Right now\n> we simply don't have any way to tell the pager what to do with the\n> data, and we'd need to do some communications passing thing to let it\n> know.\n\nThere is an alternative.  pager.c:run_pager() runs a select() to wait \nfor data before it actually exec()s the pager.  What if after the \nselect() the process didn't exec(), but read the first line to decide \nwhat pager to exec?\n\nThen, when pager_in_use is true, the sending process writes, say, a \nhandler identifier which tells the pager process what to exec().\n\n\n\nAndy\n\n-- \nDr Andy Parkins, M Eng (hons), MIET\nandyparkins@gmail.com\n"},{"id":"36135","messageId":"200703022224.28678.andyparkins@gmail.com","threadId":"7037","inReplyTo":"200703022221.38309.andyparkins@gmail.com","subject":"Re: [PATCH] Quick description of possible gitattributes system","fromName":"Andy Parkins","fromEmail":"andyparkins@gmail.com","sentAt":"2007-03-02T22:24:26Z","receivedAt":"2007-03-02T22:24:26Z","isPatch":true,"sender":{"key":"andyparkins@gmail.com","avatar":null},"body":"On Friday 2007, March 02, Andy Parkins wrote:\n\n> There is an alternative.  pager.c:run_pager() runs a select() to wait\n> for data before it actually exec()s the pager.  What if after the\n> select() the process didn't exec(), but read the first line to decide\n> what pager to exec?\n\nDuh!  I see now that that is almost exactly what you did in your patch.  \nIgnore me.\n\n\nAndy\n\n-- \nDr Andy Parkins, M Eng (hons), MIET\nandyparkins@gmail.com\n"},{"id":"36174","messageId":"7vlkiebhfl.fsf@assigned-by-dhcp.cox.net","threadId":"7037","inReplyTo":"Pine.LNX.4.64.0703020850470.3953@woody.linux-foundation.org","subject":"Re: [PATCH] Quick description of possible gitattributes system","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-03-03T13:11:26Z","receivedAt":"2007-03-03T13:11:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@linux-foundation.org> writes:\n\n> On Fri, 2 Mar 2007, Jakub Narebski wrote:\n>\n>> Andy Parkins wrote:\n>> \n>> > + - prettyfilter\n>> > +   Run by git-cat-file or git-show when content is being pretty-printed\n>> > +   for display to the user.  If no prettyfilter is set, then it should\n>> > +   default to outfilter.\n>> \n>> I'd rather have plumbing operate without filters (if it is possible),\n>> so git-cat-file would not run prettyfilter, and git-show would run it.\n>\n> That really sucks. I do \"git show xyz > filname\" all the time, and while \n> it's been about diffs and commits, I could imagine doing the same thing \n> for things like \"git show v2.6.17:Documentation/logo.gif > some.gif\" too.\n>\n> Yes, I know could do \"git cat-file -p ..\" instead, but since we added \"git \n> show\", and made it do the Right Thing (tm) for blobs, I've come to use it \n> more (which is as it should be: \"cat-file\" is low-level plumbing, while \n> \"git show\" is what you'd expect users to use.\n>\n> So I really think that the issue here is that the *pager* should do the \n> right thing...\n\nSorry, but I do not think that would work because of the way we\nsetup our pager.  The original process turns into the PAGER and\nchild ships the data to it.\n\n\t$ git show -s master maint :t/test4012.png\n\nI do not particularly think the prettyfilter is useful in\npractice (it was just a fun toy I did to convince me that I can\nuse it for things other than input/output munging), but at least\nwe could make it a bit more usable by this, on top of 'pu':\n\ndiff --git a/builtin-log.c b/builtin-log.c\nindex 86062d3..bc26358 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -116,7 +116,7 @@ static int show_object(const unsigned char *sha1, const char *path, int nohead)\n \tif (size <= offset)\n \t\tgoto finish;\n \n-\tif (path) {\n+\tif (pager_in_use && path) {\n \t\tconst struct pathattr *a = pathattr_lookup(path);\n \t\tif (a && a->pretty) {\n \t\t\tpretty = a->pretty;\n"},{"id":"36203","messageId":"200703032127.56343.jnareb@gmail.com","threadId":"7037","inReplyTo":"Pine.LNX.4.64.0703020850470.3953@woody.linux-foundation.org","subject":"Re: [PATCH] Quick description of possible gitattributes system","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-03-03T20:27:55Z","receivedAt":"2007-03-03T20:27:55Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Fri, 2 Mar 2007, Linus Torvalds wrote:\n> On Fri, 2 Mar 2007, Jakub Narebski wrote:\n>> Andy Parkins wrote:\n>> \n>>> + - prettyfilter\n>>> +   Run by git-cat-file or git-show when content is being pretty-printed\n>>> +   for display to the user.  If no prettyfilter is set, then it should\n>>> +   default to outfilter.\n>> \n>> I'd rather have plumbing operate without filters (if it is possible),\n>> so git-cat-file would not run prettyfilter, and git-show would run it.\n[...]\n> So I really think that the issue here is that the *pager* should do the \n> right thing. Which gets us to:\n> \n>> Or at least detect if output is tty, so one can do something like\n>> \"git cat-file -p v1.0.0:gitweb/git-logo.png > git-logo.png\" and get\n>> expected result, while \"git show v1.0.0:gitweb/git-logo.png\" would\n>> show the image.\n> \n> Yes. How about just having the built-in git pager do the right thing?\n> \n> Right now we actually wait for data to start arriving (commit 35ce862) due \n> to working around a bug in less. But what if we could make the pager \n> actually do the right thing here automatically? With \"less\" just being the \n> default action for *text*?\n\nWouldn't it be better and simplier instead of creating built-in magic\n(as in DWIM) pager, to have in place of \"prettyfilter\", \"pretty\",\n\"show\" handler \"pager\" handler, which would define _default_ pager for\ngiven attributes.\n\nIt would mean that the filter/sink would be run only when pager is run,\ni.e. for \"git show\" and \"git -p cat-file\"/\"git --paginate cat-file\".\nI guess that would mean that handler action would be run only for tty.\nAnd you could always override it by setting PAGER environmental variable.\n\nSo it would be:\n\n+ - pager\n+   Change default pager for this content. If it is not set, it defaults\n+   to `less'. You can always override default pager by setting PAGER\n+   environmental variable.\n\n-- \nJakub Narebski\nShadeHawk on #git\nPoland\n"}]}