{"thread":{"id":"460","subject":"git and symlinks as tracked content","startedAt":"2005-05-03T18:33:54Z","lastAt":"2005-05-06T03:01:00Z","messageCount":29,"participants":["Kay Sievers","Linus Torvalds","Morten Welinder","H. Peter Anvin","Andreas Gal","Junio C Hamano","Brian O'Mahoney","David A. Wheeler","Daniel Barkalow","Alan Chandler","David Lang","Sean"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"2496","messageId":"1115145234.21105.111.camel@localhost.localdomain","threadId":"460","inReplyTo":null,"subject":"git and symlinks as tracked content","fromName":"Kay Sievers","fromEmail":"kay.sievers@vrfy.org","sentAt":"2005-05-03T18:33:54Z","receivedAt":"2005-05-03T18:33:54Z","isPatch":false,"sender":{"key":"kay.sievers@vrfy.org","avatar":null},"body":"Is there a sane model to make git aware of tracking symlinks in the\nrepository? In the bk udev tree we've had a test sysfs-tree with a lot\nof symlinks in it.\n\nWhere can we store the link-target? In its own blob-object or directly\nin the tree-object?\n\nHow would a exported \"patch\" with symlinks as content look like?\n\nThanks,\nKay\n\n"},{"id":"2497","messageId":"Pine.LNX.4.58.0505031151240.26698@ppc970.osdl.org","threadId":"460","inReplyTo":"1115145234.21105.111.camel@localhost.localdomain","subject":"Re: git and symlinks as tracked content","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-05-03T19:02:33Z","receivedAt":"2005-05-03T19:02:33Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 3 May 2005, Kay Sievers wrote:\n>\n> Is there a sane model to make git aware of tracking symlinks in the\n> repository? In the bk udev tree we've had a test sysfs-tree with a lot\n> of symlinks in it.\n> \n> Where can we store the link-target? In its own blob-object or directly\n> in the tree-object?\n\nI'd suggest you create a blob object with the symlink name, and then in\nthe tree you point to that blob, but with the S_IFLNK value in the mode\nfield (0120000).\n\nSo you have\n\n - directories: S_IFDIR (0040000) point to \"tree\" objects for contents\n - symlinks: S_IFLNK (0120000) point to \"blob\" objects\n - executables: S_IFREG | 0755 (0100755) point to \"blob\" objects\n - regular files: S_IFREG | 0644 (0100644) point to \"blob\" objects\n\nwhich seems very sane and regular. \n\nNow, I also haev a plan for device nodes, but that one is so ugly that I'm \na bit ashamed of it. That one does:\n\n - S_IFCHR/S_IFBLK (0020000 or 0060000), with the 20-byte SHA1 not being a \n   SHA1 at all, but just the major:minor numbers in some nice binary \n   encoding. Probably: two network byte order 32-bit values, with twelve \n   bytes of some non-zero signature (the SHA1 of all zeroes should be \n   avoided, so the signature really should be soemthing else than just \n   twelve bytes of zero).\n\nThat should cover most of it.\n\n> How would a exported \"patch\" with symlinks as content look like?\n\nThe easiest way is to make this exactly the same as the \"executable bit\". \nA symlink is just a normal blob, it just has a \"symlink mode\" instead of \n\"0755\" or \"0644\" mode.\n\nWhen you think of it that way, the \"patch\" ends up falling out very \nnaturally, I think. It would look like\n\n\tNew file: filename (Mode: 0120000)\n\t--- /dev/null\n\t+++ filename\n\t@@ 0,0 1,1\n\t+symlink-value\n\n(or something, you get the idea).\n\n\t\tLinus\n"},{"id":"2498","messageId":"118833cc05050312101f2715d3@mail.gmail.com","threadId":"460","inReplyTo":"Pine.LNX.4.58.0505031151240.26698@ppc970.osdl.org","subject":"Re: git and symlinks as tracked content","fromName":"Morten Welinder","fromEmail":"mwelinder@gmail.com","sentAt":"2005-05-03T19:10:57Z","receivedAt":"2005-05-03T19:10:57Z","isPatch":false,"sender":{"key":"mwelinder@gmail.com","avatar":null},"body":"Something in the patching food chain will also need to know how to turn\nregular files into symlinks (and vice versa) in the same we ought to have\nthat for directories right now.\n\nMorten\n"},{"id":"2507","messageId":"4277D609.5050701@zytor.com","threadId":"460","inReplyTo":"Pine.LNX.4.58.0505031151240.26698@ppc970.osdl.org","subject":"Re: git and symlinks as tracked content","fromName":"H. Peter Anvin","fromEmail":"hpa@zytor.com","sentAt":"2005-05-03T19:50:33Z","receivedAt":"2005-05-03T19:50:33Z","isPatch":false,"sender":{"key":"hpa@zytor.com","avatar":null},"body":"Linus Torvalds wrote:\n> \n> So you have\n> \n>  - directories: S_IFDIR (0040000) point to \"tree\" objects for contents\n>  - symlinks: S_IFLNK (0120000) point to \"blob\" objects\n>  - executables: S_IFREG | 0755 (0100755) point to \"blob\" objects\n>  - regular files: S_IFREG | 0644 (0100644) point to \"blob\" objects\n> \n> which seems very sane and regular. \n> \n\nOne thing about using a hierarchy of \"tree\" objects... as far as I \nunderstand today, it's possible for \"git\" to represent a limited \nscattering of files underneath the root, such as keeping one's \nconfiguration files underneath one's home directory.  Scanning the whole \nhome directory to check in (or worse, out) files would suck.\n\nOn the other hand, having a single \"tree\" object for a large project \nthat would have to be constantly updated would suck, too.\n\nThis is certainly *not* mutually exclusive; it's mostly a matter of \nmaking sure that if scaffolding directory objects are necessary, that \nthey can be automatically added/created, and aren't exhaustively \nsearched for uncontrolled objects.\n\n> Now, I also haev a plan for device nodes, but that one is so ugly that I'm \n> a bit ashamed of it. That one does:\n> \n>  - S_IFCHR/S_IFBLK (0020000 or 0060000), with the 20-byte SHA1 not being a \n>    SHA1 at all, but just the major:minor numbers in some nice binary \n>    encoding. Probably: two network byte order 32-bit values, with twelve \n>    bytes of some non-zero signature (the SHA1 of all zeroes should be \n>    avoided, so the signature really should be soemthing else than just \n>    twelve bytes of zero).\n> \n\nOK, that's ugly.  I'm impressed.  :)\n\n\t-hpa\n"},{"id":"2511","messageId":"Pine.LNX.4.58.0505031255000.30768@sam.ics.uci.edu","threadId":"460","inReplyTo":"Pine.LNX.4.58.0505031151240.26698@ppc970.osdl.org","subject":"Re: git and symlinks as tracked content","fromName":"Andreas Gal","fromEmail":"gal@uci.edu","sentAt":"2005-05-03T19:57:51Z","receivedAt":"2005-05-03T19:57:51Z","isPatch":false,"sender":{"key":"gal@uci.edu","avatar":null},"body":"\n>  - S_IFCHR/S_IFBLK (0020000 or 0060000), with the 20-byte SHA1 not being a \n>    SHA1 at all, but just the major:minor numbers in some nice binary \n>    encoding. Probably: two network byte order 32-bit values, with twelve \n>    bytes of some non-zero signature (the SHA1 of all zeroes should be \n>    avoided, so the signature really should be soemthing else than just \n>    twelve bytes of zero).\n\nYuck. Thats really ugly. Right now all files have a uniform touch to them. \nFor every hash you can locate the file, determine its type/tag, unpack it, \nand check the SHA1 hash. The proposal above breaks all that. Why not just \nintroduce a new object type \"dev\" and put major minor in there. It \nwill still always hash to the same SHA1 hash value, but fits much better in the \noverall design. \n\nAndreas\n"},{"id":"2515","messageId":"Pine.LNX.4.58.0505031304140.26698@ppc970.osdl.org","threadId":"460","inReplyTo":"Pine.LNX.4.58.0505031255000.30768@sam.ics.uci.edu","subject":"Re: git and symlinks as tracked content","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-05-03T20:05:36Z","receivedAt":"2005-05-03T20:05:36Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 3 May 2005, Andreas Gal wrote:\n> \n> Yuck. Thats really ugly. Right now all files have a uniform touch to them. \n> For every hash you can locate the file, determine its type/tag, unpack it, \n> and check the SHA1 hash. The proposal above breaks all that. Why not just \n> introduce a new object type \"dev\" and put major minor in there. It \n> will still always hash to the same SHA1 hash value, but fits much better in the \n> overall design. \n\nHey, I don't personally care that much. I don't see anybody using \ncharacter device nodes in the kernel tree, and I don't think most SCM's \nsupport stuff like that anyway ;)\n\nIf you want to make it a blob (and have a use for it), go wild. \n\n\t\tLinus\n"},{"id":"2517","messageId":"1115150959.21105.116.camel@localhost.localdomain","threadId":"460","inReplyTo":"Pine.LNX.4.58.0505031304140.26698@ppc970.osdl.org","subject":"Re: git and symlinks as tracked content","fromName":"Kay Sievers","fromEmail":"kay.sievers@vrfy.org","sentAt":"2005-05-03T20:09:19Z","receivedAt":"2005-05-03T20:09:19Z","isPatch":false,"sender":{"key":"kay.sievers@vrfy.org","avatar":null},"body":"On Tue, 2005-05-03 at 13:05 -0700, Linus Torvalds wrote:\n> \n> On Tue, 3 May 2005, Andreas Gal wrote:\n> > \n> > Yuck. Thats really ugly. Right now all files have a uniform touch to them. \n> > For every hash you can locate the file, determine its type/tag, unpack it, \n> > and check the SHA1 hash. The proposal above breaks all that. Why not just \n> > introduce a new object type \"dev\" and put major minor in there. It \n> > will still always hash to the same SHA1 hash value, but fits much better in the \n> > overall design. \n> \n> Hey, I don't personally care that much. I don't see anybody using \n> character device nodes in the kernel tree, and I don't think most SCM's \n> support stuff like that anyway ;)\n\nWell, you need to be root to create device nodes, that is not a usual\nrequirement for an SCM checkout. :)\n\nKay\n\n"},{"id":"2519","messageId":"7vy8awt5wo.fsf@assigned-by-dhcp.cox.net","threadId":"460","inReplyTo":"Pine.LNX.4.58.0505031151240.26698@ppc970.osdl.org","subject":"Re: git and symlinks as tracked content","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-03T20:23:51Z","receivedAt":"2005-05-03T20:23:51Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"LT\" == Linus Torvalds <torvalds@osdl.org> writes:\n\nLT> On Tue, 3 May 2005, Kay Sievers wrote:\n>> Where can we store the link-target? In its own blob-object or directly\n>> in the tree-object?\n\nLT>  - directories: S_IFDIR (0040000) point to \"tree\" objects for contents\nLT>  - symlinks: S_IFLNK (0120000) point to \"blob\" objects\nLT>  - executables: S_IFREG | 0755 (0100755) point to \"blob\" objects\nLT>  - regular files: S_IFREG | 0644 (0100644) point to \"blob\" objects\n\nThese and the device nodes you mention would work naturally on\nthe cache side and I generally like this idea.  You need to\nupdate checkout-cache to (attempt to) create the right kind of\nfile, but that is about it.\n\nOn the diff side, things are a bit more interesting.  Both the\ngit-diff-tree-helper engine (diff.c) and git-apply-patch-script\nneed to be told about these new types of objects, or at least\ntightened up to ignore them until they know how to support them.\n\nLT> When you think of it that way, the \"patch\" ends up falling out very \nLT> naturally, I think. It would look like\n\nLT> \tNew file: filename (Mode: 0120000)\nLT> \t--- /dev/null\nLT> \t+++ filename\nLT> \t@@ 0,0 1,1\nLT> \t+symlink-value\n\nLT> (or something, you get the idea).\n\nI've always wanted to have this from the normal \"diff -r\"\noutput, but we have to be careful.  You do not want to\naccidentally feed the normal patch that kind of output.  How\nabout doing something like this?\n\nGIT: filename (mode:120000)\n --- /dev/null\n +++ filename\n @@ -0,0 +1 @@\n +symlink-value\n\nGIT: filename (mode:120000)\n --- filename\n +++ /dev/null\n @@ -1 +0,0 @@\n -symlink-value\n\nGIT: filename (mode:120000->120000)\n --- filename\n +++ filename\n @@ -1 +1 @@\n -old-symlink-value\n +new-symlink-value\n\nThat is, to indent them to keep patch from noticing them [*1*].\n\nAbout the device nodes, the diffed contents would be major and\nminor in decimal notation, and the real filesystem permission\nbits and ownerships (e.g. changing /dev/audio from 0600 to 0660\nor from root:root to root:audio).  I do not know if we would\nwant owner/group in symbolic or numeric yet.\n\nGIT: filename (mode:0020000->0020000)\n --- dev/audio\n +++ dev/audio\n @@ -1,5 +1,5 @@\n  major=14\n  minor=4\n  owner=root\n -group=root\n -perm=0600\n +group=audio\n +perm=0660\n\n[Footnote]\n\n*1* A careful but not careful enough reader would wonder if the use\nof \"--- /dev/null\" or \"+++ /dev/null\" to represent an addition\nand a deletion may hamper managing the device node \"/dev/null\",\nbut this is not a problem.  Such a device node managed by GIT\nwill appear as \"--- dev/null\" or \"+++ dev/null\", without the\nleading slash.\n\n"},{"id":"2526","messageId":"7vr7got2tz.fsf@assigned-by-dhcp.cox.net","threadId":"460","inReplyTo":"Pine.LNX.4.58.0505031304140.26698@ppc970.osdl.org","subject":"Re: git and symlinks as tracked content","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-03T21:30:16Z","receivedAt":"2005-05-03T21:30:16Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"LT\" == Linus Torvalds <torvalds@osdl.org> writes:\n\nLT> On Tue, 3 May 2005, Andreas Gal wrote:\n\n>> Yuck. Thats really ugly. Right now all files have a uniform\n>> touch to them.  For every hash you can locate the file,\n>> determine its type/tag, unpack it, and check the SHA1\n>> hash. The proposal above breaks all that. Why not just\n>> introduce a new object type \"dev\" and put major minor in\n>> there. It will still always hash to the same SHA1 hash value,\n>> but fits much better in the overall design.\n\nLT> Hey, I don't personally care that much. I don't see anybody using \nLT> character device nodes in the kernel tree, and I don't think most SCM's \nLT> support stuff like that anyway ;)\n\nLT> If you want to make it a blob (and have a use for it), go wild. \n\nIntroducing \"dev\" type, as Andreas suggests, is wrong.  This\nthis should be done in the same way as you suggested for the\nsymlink case.  Store a blob object with those chrdev or blkdev\nmodes whose contents are of form:\n\n    major=14\n    minor=4\n    owner=root\n    group=audio\n    perm=0660\n\nThis would impact the diff side least, and for the cache side it\ndoes not matter in storing and merging.  checkout-cache still\nneeds to know about this.\n\n"},{"id":"2533","messageId":"Pine.LNX.4.58.0505031446220.31626@sam.ics.uci.edu","threadId":"460","inReplyTo":"7vr7got2tz.fsf@assigned-by-dhcp.cox.net","subject":"Re: git and symlinks as tracked content","fromName":"Andreas Gal","fromEmail":"gal@uci.edu","sentAt":"2005-05-03T21:51:18Z","receivedAt":"2005-05-03T21:51:18Z","isPatch":false,"sender":{"key":"gal@uci.edu","avatar":null},"body":"\nWhether you use an explicit \"dev\" type or an implicit \"dev\" type that \ncalls itself \"blob\" and uses a magic mode flag to tell checkout that it \nneeds special treatment doesn't make a difference (whatever you \nprefer, really). I was only trying to make the point that hashes should remain \nhashes and not become a placeholder for minors/majors. However, as \nsomebody already suggested, the entire issue is probably moot. When was the last \ntime you tried to version control /dev? ;)\n\nAndreas\n\nOn Tue, 3 May 2005, Junio C Hamano wrote:\n\n> >>>>> \"LT\" == Linus Torvalds <torvalds@osdl.org> writes:\n> \n> LT> On Tue, 3 May 2005, Andreas Gal wrote:\n> \n> >> Yuck. Thats really ugly. Right now all files have a uniform\n> >> touch to them.  For every hash you can locate the file,\n> >> determine its type/tag, unpack it, and check the SHA1\n> >> hash. The proposal above breaks all that. Why not just\n> >> introduce a new object type \"dev\" and put major minor in\n> >> there. It will still always hash to the same SHA1 hash value,\n> >> but fits much better in the overall design.\n> \n> LT> Hey, I don't personally care that much. I don't see anybody using \n> LT> character device nodes in the kernel tree, and I don't think most SCM's \n> LT> support stuff like that anyway ;)\n> \n> LT> If you want to make it a blob (and have a use for it), go wild. \n> \n> Introducing \"dev\" type, as Andreas suggests, is wrong.  This\n> this should be done in the same way as you suggested for the\n> symlink case.  Store a blob object with those chrdev or blkdev\n> modes whose contents are of form:\n> \n>     major=14\n>     minor=4\n>     owner=root\n>     group=audio\n>     perm=0660\n> \n> This would impact the diff side least, and for the cache side it\n> does not matter in storing and merging.  checkout-cache still\n> needs to know about this.\n> \n> -\n> To unsubscribe from this list: send the line \"unsubscribe git\" in\n> the body of a message to majordomo@vger.kernel.org\n> More majordomo info at  http://vger.kernel.org/majordomo-info.html\n> \n"},{"id":"2539","messageId":"7v8y2wszdy.fsf@assigned-by-dhcp.cox.net","threadId":"460","inReplyTo":"Pine.LNX.4.58.0505031446220.31626@sam.ics.uci.edu","subject":"Re: git and symlinks as tracked content","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-03T22:44:41Z","receivedAt":"2005-05-03T22:44:41Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"AG\" == Andreas Gal <gal@uci.edu> writes:\n\nAG> Whether you use an explicit \"dev\" type or an implicit \"dev\"\nAG> type that calls itself \"blob\" and uses a magic mode flag to\nAG> tell checkout that it needs special treatment doesn't make a\nAG> difference.\n\nTrue.  The use of word \"wrong\" in my message was _wrong_.  But\nmy gut feeling is that the code that has to deal with the dev\nand symlink stuff would be simpler if we just stick to the blob\ntype.\n\nAG> When was the last time you tried to version control /dev? ;)\n\nTried?  Never.  Wished?  Number of times.  It's just that there\nis no such SCM that does this natively, so I keep \"ls -l /dev\"\noutput under CVS control as a rough approximation.\n\n"},{"id":"2540","messageId":"42780185.7010204@zytor.com","threadId":"460","inReplyTo":"7vr7got2tz.fsf@assigned-by-dhcp.cox.net","subject":"Re: git and symlinks as tracked content","fromName":"H. Peter Anvin","fromEmail":"hpa@zytor.com","sentAt":"2005-05-03T22:56:05Z","receivedAt":"2005-05-03T22:56:05Z","isPatch":false,"sender":{"key":"hpa@zytor.com","avatar":null},"body":"Junio C Hamano wrote:\n> \n> Introducing \"dev\" type, as Andreas suggests, is wrong.  This\n> this should be done in the same way as you suggested for the\n> symlink case.  Store a blob object with those chrdev or blkdev\n> modes whose contents are of form:\n> \n>     major=14\n>     minor=4\n>     owner=root\n>     group=audio\n>     perm=0660\n> \n> This would impact the diff side least, and for the cache side it\n> does not matter in storing and merging.  checkout-cache still\n> needs to know about this.\n> \n\nOwner and permissions are part of the tree object, and apply to all file \ntypes.  The only thing equivalent to file data is the major,minor; \nstoring it as a comma-separated decimal ASCII string is probably the \ncleanest, i.e. for your exaple:\n\n14,4\n\n\t-hpa\n"},{"id":"2544","messageId":"7v1x8nuchr.fsf@assigned-by-dhcp.cox.net","threadId":"460","inReplyTo":"42780185.7010204@zytor.com","subject":"Re: git and symlinks as tracked content","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-03T23:16:16Z","receivedAt":"2005-05-03T23:16:16Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"HPA\" == H Peter Anvin <hpa@zytor.com> writes:\n\nHPA> Owner and permissions are part of the tree object, and apply to all\nHPA> file types.\n\nHuh?  I am confused...  Do you mean tree object should be\nchanged to record these?  That would make the existing in-cache\nmerging of files, which GIT was built for, quite interesting...\n\nWell, doing device nodes _is_ a tangent, so let's drop this\ndiscussion.\n\n\n"},{"id":"2545","messageId":"427806CA.6030302@zytor.com","threadId":"460","inReplyTo":"7v1x8nuchr.fsf@assigned-by-dhcp.cox.net","subject":"Re: git and symlinks as tracked content","fromName":"H. Peter Anvin","fromEmail":"hpa@zytor.com","sentAt":"2005-05-03T23:18:34Z","receivedAt":"2005-05-03T23:18:34Z","isPatch":false,"sender":{"key":"hpa@zytor.com","avatar":null},"body":"Junio C Hamano wrote:\n>>>>>>\"HPA\" == H Peter Anvin <hpa@zytor.com> writes:\n> \n> \n> HPA> Owner and permissions are part of the tree object, and apply to all\n> HPA> file types.\n> \n> Huh?  I am confused...  Do you mean tree object should be\n> changed to record these?  That would make the existing in-cache\n> merging of files, which GIT was built for, quite interesting...\n> \n> Well, doing device nodes _is_ a tangent, so let's drop this\n> discussion.\n> \n\nNo, the tree object *ALREADY* records these.\n\nBLOB: A \"blob\" object is nothing but a binary blob of data, and doesn't\nrefer to anything else.  There is no signature or any other verification\nof the data, so while the object is consistent (it _is_ indexed by its\nsha1 hash, so the data itself is certainly correct), it has absolutely\nno other attributes.  No name associations, no permissions.  It is\npurely a blob of data (ie normally \"file contents\").\n\nTREE: The next hierarchical object type is the \"tree\" object.  A tree\nobject is a list of permission/name/blob data, sorted by name.  In other\nwords the tree object is uniquely determined by the set contents, and so\ntwo separate but identical trees will always share the exact same\nobject.\n\n\t-hpa\n"},{"id":"2549","messageId":"Pine.LNX.4.58.0505031632400.26698@ppc970.osdl.org","threadId":"460","inReplyTo":"427806CA.6030302@zytor.com","subject":"Re: git and symlinks as tracked content","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-05-03T23:42:00Z","receivedAt":"2005-05-03T23:42:00Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 3 May 2005, H. Peter Anvin wrote:\n> \n> No, the tree object *ALREADY* records these.\n\nNot ownership.\n\nYes, the permissions are there, but if you actually want to track \nownership (or things like \"mtime\" etc), you really do have to track it \noutside the tree object.\n\nAlso, right now git will actually ignore most of the permission bits too.  \nWe can change that, and make it a dynamic setting somewhere (some flag in\na \".git/settings\" file or something), but it does boil down to the fact\nthat a software development tree tracker wants different things than\nsomething that tracks system settings.\n\nFor example, generating different trees just because different users had\ndifferent umask settings clearly didn't work out. Which means that right\nnow git really only tracks the \"owner execute\" bit of the permissions, and\nalways resets the other bits to 0755 or 0644 depending on that _one_ bit.\n\nAnd similarly, tracking actual uid/gid information would _really_ not work \nfor a distributed kernel source management system, so that's not even in \nthe tree.\n\nSo if you want to track system files, right now \"raw git\" is _not_ the way \nto do it. You'd want something else. \n\nOf course, that's actually true largely even of normal /dev contents.  \nThat's why we've moved towards udev, and having things like device\npermissions and ownership not be \"filesystem attributes\", but really\n_rules_ in a udev database. So the fact that git doesn't track them isn't\nnecessarily a problem for /dev - since modern /dev really wants to track\nthem at a higher level _anyway_ (and you'd use git to track the _rules_,\nnot the ownership things themselves).\n\nBut if you'd want to track other system directories with git, you'd\nprobably need to either (a) do serious surgery on git itself, or (probably\npreferable) by (b) track the extra things you want \"manually\" using a file\n(that is tracked in git) that describes the ownership and permission data.\n\nWhether git is really suitable for tracking non-source projects is\nobviously debatable. It's not what it was designed for, and it _may_ be \nable to do so partly just by luck.\n\n\t\t\tLinus\n"},{"id":"2550","messageId":"7vhdhjswp3.fsf@assigned-by-dhcp.cox.net","threadId":"460","inReplyTo":"427806CA.6030302@zytor.com","subject":"Re: git and symlinks as tracked content","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-03T23:42:48Z","receivedAt":"2005-05-03T23:42:48Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"HPA\" == H Peter Anvin <hpa@zytor.com> writes:\nHPA> Junio C Hamano wrote:\n\nHPA> Owner and permissions are part of the tree object, and apply to\nHPA> all file types.\n\n>> Huh?  I am confused...  Do you mean tree object should be\n>> changed to record these?  That would make the existing in-cache\n>> merging of files, which GIT was built for, quite interesting...\n\nHPA> No, the tree object *ALREADY* records these.\n\nAs you quoted (and before I uttered my previous confusion I did\nlook at the code in write-tree.c which I thought to match this\ndescription) ...\n\nHPA> TREE: The next hierarchical object type is the \"tree\" object.  A tree\nHPA> object is a list of permission/name/blob data, sorted by name.  In other\nHPA> words the tree object is uniquely determined by the set contents, and so\nHPA> two separate but identical trees will always share the exact same\nHPA> object.\n\n... it records permission (but not in the 0660 vs 0600 sense ---\nit just records executable bit for file blobs and the treeness\nby recording S_IFDIR), name and SHA1.  There is no owner or\ngroup information recorded there [*1*].\n\nI am afraid I am missing something in my reading of write-tree.c\n\nQuite confused...\n\n[Footnote]\n\n*1* Nor there should be.  Otherwise comparing two identical\ntrees representing the same set of files become meaningless.\n\nThe reason why I placed these information in my hypothetical\nrepresentation of device nodes is exactly that.  To record owner\nand group information is meaningless and harmful for the purpose\nof version controlling the source files but it matters _if_ we\nwanted to maintain device nodes in GIT.  Since it matters only\nfor those things, it would be preferable to have it as part of\nthe data that describes the object (i.e. device nodes), not part\nof the data that contains the object (i.e. tree).  And I thought\nGIT tree object is already doing the right thing by not\nrecording them.\n\n\n"},{"id":"2554","messageId":"427819B7.3010706@khandalf.com","threadId":"460","inReplyTo":"7v8y2wszdy.fsf@assigned-by-dhcp.cox.net","subject":"Sym-links, b/c-special files, pipes, ... Scope Creep","fromName":"Brian O'Mahoney","fromEmail":"omb@khandalf.com","sentAt":"2005-05-04T00:39:19Z","receivedAt":"2005-05-04T00:39:19Z","isPatch":false,"sender":{"key":"omb@khandalf.com","avatar":null},"body":"Caution, let us all carefully understand the Source-Code/\nConfiguration Management issue.\n\nI for one will be very happy if we get a really good distributed\nSCM out of this.\n\nBrian\n"},{"id":"2577","messageId":"4278EEC6.2090607@dwheeler.com","threadId":"460","inReplyTo":"42780185.7010204@zytor.com","subject":"Re: git and symlinks as tracked content","fromName":"David A. Wheeler","fromEmail":"dwheeler@dwheeler.com","sentAt":"2005-05-04T15:48:22Z","receivedAt":"2005-05-04T15:48:22Z","isPatch":false,"sender":{"key":"dwheeler@dwheeler.com","avatar":"https://avatars.githubusercontent.com/u/813150?v=4"},"body":"Linus Torvalds wrote:\n >Also, right now git will actually ignore most of the permission bits \ntoo.  \n >We can change that, and make it a dynamic setting somewhere (some flag in\n >a \".git/settings\" file or something), but it does boil down to the fact\n >that a software development tree tracker wants different things than\n >something that tracks system settings.\n...\n >So if you want to track system files, right now \"raw git\" is _not_ the \nway\n >to do it. You'd want something else.\n...\n >But if you'd want to track other system directories with git, you'd\n >probably need to either (a) do serious surgery on git itself, or (probably\n >preferable) by (b) track the extra things you want \"manually\" using a file\n >(that is tracked in git) that describes the ownership and permission data.\n >\n >Whether git is really suitable for tracking non-source projects is\n >obviously debatable. It's not what it was designed for, and it _may_ be\n >able to do so partly just by luck.\n\nI suspect there's a 95% point which is easily achieved, &\nbeyond that it's not clear it's worth it.\n\nI recall seeing several source code directories that actually use symlinks\nin their source, and thus would want them preserved by the SCM.\n(Not arguing that's the BEST plan, merely an observation).\nAs this discussion has noted, that wouldn't be hard to add symlink\nsupport to git, and WOULD be helpful for its primary purpose as SCM support.\n\nOnce you're there, it wouldn't be hard to add logic to add options to\n(1) record the REAL permission bits, (2) record \".\" files, and\n(3) recover the permission bits.  That would be enough to\nstore & recover in a distributed way a single person's home directory.\nTHAT might be darn useful, for those of us who float between\ndifferent systems & would like to use a single system for multiple purposes.\nThat's clearly beyond the scope of a typical SCM, but since\nit's easy to get there, that'd make sense.\n\nI'm ambivalent about supporting dev, uid/gid, and mtime, and how\nit should be done; that may be beyond the \"worth it\" step.\n\n--- David A. Wheeler\n\n"},{"id":"2593","messageId":"20050504223532.GA22967@vrfy.org","threadId":"460","inReplyTo":"Pine.LNX.4.58.0505031151240.26698@ppc970.osdl.org","subject":"Re: git and symlinks as tracked content","fromName":"Kay Sievers","fromEmail":"kay.sievers@vrfy.org","sentAt":"2005-05-04T22:35:32Z","receivedAt":"2005-05-04T22:35:32Z","isPatch":false,"sender":{"key":"kay.sievers@vrfy.org","avatar":null},"body":"On Tue, May 03, 2005 at 12:02:33PM -0700, Linus Torvalds wrote:\n> \n> \n> On Tue, 3 May 2005, Kay Sievers wrote:\n> >\n> > Is there a sane model to make git aware of tracking symlinks in the\n> > repository? In the bk udev tree we've had a test sysfs-tree with a lot\n> > of symlinks in it.\n> > \n> > Where can we store the link-target? In its own blob-object or directly\n> > in the tree-object?\n> \n> I'd suggest you create a blob object with the symlink name, and then in\n> the tree you point to that blob, but with the S_IFLNK value in the mode\n> field (0120000).\n> \n> So you have\n> \n>  - directories: S_IFDIR (0040000) point to \"tree\" objects for contents\n>  - symlinks: S_IFLNK (0120000) point to \"blob\" objects\n>  - executables: S_IFREG | 0755 (0100755) point to \"blob\" objects\n>  - regular files: S_IFREG | 0644 (0100644) point to \"blob\" objects\n> \n> which seems very sane and regular. \n\nHere is a first try, that is able to track symlinks. Please have a look\nif something like this is acceptable, then I will finish it.\n\nThanks,\nKay\n\n--- a/check-files.c\n+++ b/check-files.c\n@@ -28,8 +28,8 @@ static void check_file(const char *path)\n \t\tdie(\"preparing to update existing file '%s' not in cache\", path);\n \tce = active_cache[pos];\n \n-\tif (fstat(fd, &st) < 0)\n-\t\tdie(\"fstat(%s): %s\", path, strerror(errno));\n+\tif (lstat(path, &st) < 0)\n+\t\tdie(\"lstat(%s): %s\", path, strerror(errno));\n \n \tchanged = cache_match_stat(ce, &st);\n \tif (changed)\n--- a/checkout-cache.c\n+++ b/checkout-cache.c\n@@ -72,23 +72,37 @@ static int write_entry(struct cache_entr\n \tunsigned long size;\n \tlong wrote;\n \tchar type[20];\n+\tunsigned int mode;\n \n \tnew = read_sha1_file(ce->sha1, type, &size);\n \tif (!new || strcmp(type, \"blob\")) {\n \t\treturn error(\"checkout-cache: unable to read sha1 file of %s (%s)\",\n \t\t\tpath, sha1_to_hex(ce->sha1));\n \t}\n-\tfd = create_file(path, ntohl(ce->ce_mode));\n-\tif (fd < 0) {\n+\tmode = ntohl(ce->ce_mode);\n+\tif (S_ISLNK(mode)) {\n+\t\tchar target[1024];\n+\t\tmemcpy(target, new, size);\n+\t\ttarget[size] = '\\0';\n+\t\tif (symlink(target, path)) {\n+\t\t\tfree(new);\n+\t\t\treturn error(\"checkout-cache: unable to create link %s (%s)\",\n+\t\t\t\tpath, strerror(errno));\n+\t\t}\n+\t\tfree(new);\n+\t} else {\n+\t\tfd = create_file(path, mode);\n+\t\tif (fd < 0) {\n+\t\t\tfree(new);\n+\t\t\treturn error(\"checkout-cache: unable to create file %s (%s)\",\n+\t\t\t\tpath, strerror(errno));\n+\t\t}\n+\t\twrote = write(fd, new, size);\n+\t\tclose(fd);\n \t\tfree(new);\n-\t\treturn error(\"checkout-cache: unable to create %s (%s)\",\n-\t\t\tpath, strerror(errno));\n+\t\tif (wrote != size)\n+\t\t\treturn error(\"checkout-cache: unable to write %s\", path);\n \t}\n-\twrote = write(fd, new, size);\n-\tclose(fd);\n-\tfree(new);\n-\tif (wrote != size)\n-\t\treturn error(\"checkout-cache: unable to write %s\", path);\n \treturn 0;\n }\n \n@@ -101,7 +115,7 @@ static int checkout_entry(struct cache_e\n \tmemcpy(path, base_dir, len);\n \tstrcpy(path + len, ce->name);\n \n-\tif (!stat(path, &st)) {\n+\tif (!lstat(path, &st)) {\n \t\tunsigned changed = cache_match_stat(ce, &st);\n \t\tif (!changed)\n \t\t\treturn 0;\n--- a/diff-cache.c\n+++ b/diff-cache.c\n@@ -24,7 +24,7 @@ static int get_stat_data(struct cache_en\n \t\tstatic unsigned char no_sha1[20];\n \t\tint changed;\n \t\tstruct stat st;\n-\t\tif (stat(ce->name, &st) < 0)\n+\t\tif (lstat(ce->name, &st) < 0)\n \t\t\treturn -1;\n \t\tchanged = cache_match_stat(ce, &st);\n \t\tif (changed) {\n--- a/ls-files.c\n+++ b/ls-files.c\n@@ -199,7 +199,7 @@ static void show_files(void)\n \t\t\tstruct stat st;\n \t\t\tif (excluded(ce->name) != show_ignored)\n \t\t\t\tcontinue;\n-\t\t\tif (!stat(ce->name, &st))\n+\t\t\tif (!lstat(ce->name, &st))\n \t\t\t\tcontinue;\n \t\t\tprintf(\"%s%c\", ce->name, line_terminator);\n \t\t}\n--- a/tree.c\n+++ b/tree.c\n@@ -13,7 +13,10 @@ static int read_one_entry(unsigned char \n \n \tmemset(ce, 0, size);\n \n-\tce->ce_mode = create_ce_mode(mode);\n+\tif (mode & S_IFMT)\n+\t\tce->ce_mode = htonl(mode);\n+\telse\n+\t\tce->ce_mode = create_ce_mode(mode);\n \tce->ce_flags = create_ce_flags(baselen + len, stage);\n \tmemcpy(ce->name, base, baselen);\n \tmemcpy(ce->name + baselen, pathname, len+1);\n--- a/update-cache.c\n+++ b/update-cache.c\n@@ -58,30 +58,37 @@ static int add_file_to_cache(char *path)\n \tstruct stat st;\n \tint fd;\n \n-\tfd = open(path, O_RDONLY);\n-\tif (fd < 0) {\n+\tif (lstat(path, &st) < 0) {\n \t\tif (errno == ENOENT || errno == ENOTDIR) {\n \t\t\tif (allow_remove)\n \t\t\t\treturn remove_file_from_cache(path);\n \t\t}\n \t\treturn -1;\n \t}\n-\tif (fstat(fd, &st) < 0) {\n-\t\tclose(fd);\n-\t\treturn -1;\n-\t}\n \tnamelen = strlen(path);\n \tsize = cache_entry_size(namelen);\n \tce = xmalloc(size);\n \tmemset(ce, 0, size);\n \tmemcpy(ce->name, path, namelen);\n \tfill_stat_cache_info(ce, &st);\n-\tce->ce_mode = create_ce_mode(st.st_mode);\n+\tif (S_ISREG(st.st_mode)) {\n+\t\tfd = open(path, O_RDONLY);\n+\t\tif (fd < 0)\n+\t\t\treturn -1;\n+\t\tce->ce_mode = create_ce_mode(st.st_mode);\n+\t\tif (index_fd(ce->sha1, fd, &st) < 0)\n+\t\t\treturn -1;\n+\t} else if (S_ISLNK(st.st_mode)) {\n+\t\tunsigned int len;\n+\t\tchar target[1024];\n+\t\tce->ce_mode = htonl(S_IFLNK);\n+\t\tlen = readlink(path, target, sizeof(target));\n+\t\tif (len == -1 || len+1 > sizeof(target))\n+\t\t\treturn -1;\n+\t\tif (write_sha1_file(target, len, \"blob\", ce->sha1))\n+\t\t\treturn -1;\n+\t}\n \tce->ce_flags = htons(namelen);\n-\n-\tif (index_fd(ce->sha1, fd, &st) < 0)\n-\t\treturn -1;\n-\n \treturn add_cache_entry(ce, allow_add);\n }\n \n@@ -137,7 +144,7 @@ static struct cache_entry *refresh_entry\n \tstruct cache_entry *updated;\n \tint changed, size;\n \n-\tif (stat(ce->name, &st) < 0)\n+\tif (lstat(ce->name, &st) < 0)\n \t\treturn ERR_PTR(-errno);\n \n \tchanged = cache_match_stat(ce, &st);\n\n"},{"id":"2595","messageId":"Pine.LNX.4.21.0505041854040.30848-100000@iabervon.org","threadId":"460","inReplyTo":"4278EEC6.2090607@dwheeler.com","subject":"Re: git and symlinks as tracked content","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-05-04T23:03:25Z","receivedAt":"2005-05-04T23:03:25Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Wed, 4 May 2005, David A. Wheeler wrote:\n\n> Once you're there, it wouldn't be hard to add logic to add options to\n> (1) record the REAL permission bits, (2) record \".\" files, and\n> (3) recover the permission bits.  That would be enough to\n> store & recover in a distributed way a single person's home directory.\n> THAT might be darn useful, for those of us who float between\n> different systems & would like to use a single system for multiple purposes.\n> That's clearly beyond the scope of a typical SCM, but since\n> it's easy to get there, that'd make sense.\n\nThe status quo with respect to the permissions is actually the correct\nthing for an SCM, because you want to generate the corresponding tree for\na different user (e.g., with the other user's umask applied, etc.), not\nthe same tree.\n\nThis is a situation in which doing 90% of one thing, and then supporting\n90% of something else separately is best. What you really want is to have\na \"directory\" object type that stores the exact permissions, and the\nuid/gid, and even xattr stuff. Then you use those for distributing your\nhome directory, but not for distributing source trees, where that stuff is\nuseless and somewhat wrong. You could probably have the same kind of\ncommit objects, although you still need some way of figuring out what kind\nof object is desired for the directories in a commit.\n\n(on the other hand, it might make sense for git to handle files starting\nwith '.', and only skip .git).\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"},{"id":"2596","messageId":"7vwtqemvjt.fsf@assigned-by-dhcp.cox.net","threadId":"460","inReplyTo":"20050504223532.GA22967@vrfy.org","subject":"Re: git and symlinks as tracked content","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-04T23:16:22Z","receivedAt":"2005-05-04T23:16:22Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"It seems to follow the original suggestion by Linus and looks\ngood.  Some comments:\n\n * It continues to assume that S_IFREG, S_IFDIR and S_IFLNK have\n   the same bit pattern everywhere.  In the same spirit as we\n   store mode bits in network byte order, it may be a good time\n   to introduce something like this:\n\n   -#define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644)\n   -#define create_ce_mode(mode) htonl(S_IFREG | ce_permissions(mode))\n   +#define CE_IFREG  0100000\n   +#define CE_IFDIR  0040000\n   +#define CE_IFLNK  0120000\n   +#define CE_IFMASK 0770000\n   +\n   +#define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644) /* REG only */ \n   +#define create_ce_mode(mode) htonl(S_ISREG(mode) ?\n   +\t\t\t\t   (CE_IFREG | ce_permissions(mode)) :\n   +\t\t\t\t   S_ISLNK(mode) ?\n   +\t\t\t\t   CE_IFLNK :\n   +\t\t\t\t   0) /* what would we do for unknowns? */\n\n * read-cache.c:cache_match_stat() needs to know about the\n   object type.  It was allowed to assume that anything thrown\n   at it was a file, but not anymore.  How about something like\n   this:\n\n     int cache_match_stat(struct cache_entry \n     {\n            unsigned int changed = 0;\n\n    +       switch (ntohl(ce->ce_mode) & CE_IFMASK) {\n    +       case CE_IFREG:\n    +               changed |= !S_ISREG(st->st_mode) ? TYPE_CHANGED : 0;\n    +               break;\n    +       case CE_IFLNK:\n    +               changed |= !S_ISLNK(st->st_mode) ? TYPE_CHANGED : 0;\n    +               break;\n    +       default:\n    +               die(\"internal error: ce_mode is %o\", ntohl(ce->ce_mode));\n    +       }\n\n    (in cache.h) \n     #define INODE_CHANGED   0x0010\n     #define DATA_CHANGED    0x0020\n    +#define TYPE_CHANGED    0x0040\n\n  * update-cache.c:refresh_entry() needs to know that if the\n    type of the path changed, it would never match:\n\n            /*\n    -        * If the mode has changed, there's no point in trying\n    +        * If the mode or type has changed, there's no point in trying\n             * to refresh the entry - it's not going to match\n             */\n    -       if (changed & MODE_CHANGED)\n    +       if (changed & (MODE_CHANGED | TYPE_CHANGED))\n                    return ERR_PTR(-EINVAL);\n\n            if (compare_data(ce, st.st_size))\n\n  * (this is just a minor nit).  Since you have st here,\n    st.st_size can be used to see how big a buffer you need to\n    prepare for readlink() here:\n\n    +               unsigned int len;\n    +               char target[1024];\n    +               ce->ce_mode = htonl(S_IFLNK);\n    +               len = readlink(path, target, sizeof(target));\n    +               if (len == -1 || len+1 > sizeof(target))\n    +                       return -1;\n\n  * Probably diff.c needs to be made aware of this change.\n\n"},{"id":"2604","messageId":"20050505012051.GA26201@vrfy.org","threadId":"460","inReplyTo":"7vwtqemvjt.fsf@assigned-by-dhcp.cox.net","subject":"Re: git and symlinks as tracked content","fromName":"Kay Sievers","fromEmail":"kay.sievers@vrfy.org","sentAt":"2005-05-05T01:20:51Z","receivedAt":"2005-05-05T01:20:51Z","isPatch":false,"sender":{"key":"kay.sievers@vrfy.org","avatar":null},"body":"Allow to store and track symlink in the repository. A symlink is stored\nthe same way as a regular file, but with the appropriate mode bits set.\nThe symlink target is stored in its own blob object. This will hopefully\nmake our udev repository fully functional. :)\n\nSigned-off-by: Kay Sievers <kay.sievers@vrfy.org>\n---\n\nOn Wed, May 04, 2005 at 04:16:22PM -0700, Junio C Hamano wrote:\n> It seems to follow the original suggestion by Linus and looks\n> good.  Some comments:\n>\n>  * It continues to assume that S_IFREG, S_IFDIR and S_IFLNK have\n>    the same bit pattern everywhere.  In the same spirit as we\n>    store mode bits in network byte order, it may be a good time\n>    to introduce something like this:\n...\n\n>  * read-cache.c:cache_match_stat() needs to know about the\n>    object type.  It was allowed to assume that anything thrown\n>    at it was a file, but not anymore.  How about something like\n>    this:\n\nBoth included and updated.\n\n>   * (this is just a minor nit).  Since you have st here,\n>     st.st_size can be used to see how big a buffer you need to\n>     prepare for readlink() here:\n\nSounds nice, but is this reliable? I just remember some exotic filesystems\nto reported bogus values here.\n\n>   * Probably diff.c needs to be made aware of this change.\n\nYou already did this. :) Very nice.\n\nThanks,\nKay\n\n--- a/cache.h\n+++ b/cache.h\n@@ -86,8 +86,19 @@ struct cache_entry {\n #define ce_size(ce) cache_entry_size(ce_namelen(ce))\n #define ce_stage(ce) ((CE_STAGEMASK & ntohs((ce)->ce_flags)) >> CE_STAGESHIFT)\n \n+#define CE_IFREG  0100000\n+#define CE_IFDIR  0040000\n+#define CE_IFLNK  0120000\n+#define CE_IFMASK 0770000\n #define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644)\n-#define create_ce_mode(mode) htonl(S_IFREG | ce_permissions(mode))\n+static inline unsigned int create_ce_mode(unsigned int mode)\n+{\n+\tif (S_ISREG(mode))\n+\t\treturn htonl(S_IFREG | ce_permissions(mode));\n+\tif (S_ISLNK(mode))\n+\t\treturn htonl(CE_IFLNK);\n+\treturn 0;\n+}\n \n #define cache_entry_size(len) ((offsetof(struct cache_entry,name) + (len) + 8) & ~7)\n \n@@ -124,6 +135,7 @@ extern int index_fd(unsigned char *sha1,\n #define MODE_CHANGED    0x0008\n #define INODE_CHANGED   0x0010\n #define DATA_CHANGED    0x0020\n+#define TYPE_CHANGED    0x0040\n \n /* Return a statically allocated filename matching the sha1 signature */\n extern char *sha1_file_name(const unsigned char *sha1);\n--- a/check-files.c\n+++ b/check-files.c\n@@ -28,8 +28,8 @@ static void check_file(const char *path)\n \t\tdie(\"preparing to update existing file '%s' not in cache\", path);\n \tce = active_cache[pos];\n \n-\tif (fstat(fd, &st) < 0)\n-\t\tdie(\"fstat(%s): %s\", path, strerror(errno));\n+\tif (lstat(path, &st) < 0)\n+\t\tdie(\"lstat(%s): %s\", path, strerror(errno));\n \n \tchanged = cache_match_stat(ce, &st);\n \tif (changed)\n--- a/checkout-cache.c\n+++ b/checkout-cache.c\n@@ -72,23 +72,37 @@ static int write_entry(struct cache_entr\n \tunsigned long size;\n \tlong wrote;\n \tchar type[20];\n+\tunsigned int mode;\n \n \tnew = read_sha1_file(ce->sha1, type, &size);\n \tif (!new || strcmp(type, \"blob\")) {\n \t\treturn error(\"checkout-cache: unable to read sha1 file of %s (%s)\",\n \t\t\tpath, sha1_to_hex(ce->sha1));\n \t}\n-\tfd = create_file(path, ntohl(ce->ce_mode));\n-\tif (fd < 0) {\n+\tmode = ntohl(ce->ce_mode);\n+\tif (S_ISLNK(mode)) {\n+\t\tchar target[1024];\n+\t\tmemcpy(target, new, size);\n+\t\ttarget[size] = '\\0';\n+\t\tif (symlink(target, path)) {\n+\t\t\tfree(new);\n+\t\t\treturn error(\"checkout-cache: unable to create link %s (%s)\",\n+\t\t\t\tpath, strerror(errno));\n+\t\t}\n+\t\tfree(new);\n+\t} else {\n+\t\tfd = create_file(path, mode);\n+\t\tif (fd < 0) {\n+\t\t\tfree(new);\n+\t\t\treturn error(\"checkout-cache: unable to create file %s (%s)\",\n+\t\t\t\tpath, strerror(errno));\n+\t\t}\n+\t\twrote = write(fd, new, size);\n+\t\tclose(fd);\n \t\tfree(new);\n-\t\treturn error(\"checkout-cache: unable to create %s (%s)\",\n-\t\t\tpath, strerror(errno));\n+\t\tif (wrote != size)\n+\t\t\treturn error(\"checkout-cache: unable to write %s\", path);\n \t}\n-\twrote = write(fd, new, size);\n-\tclose(fd);\n-\tfree(new);\n-\tif (wrote != size)\n-\t\treturn error(\"checkout-cache: unable to write %s\", path);\n \treturn 0;\n }\n \n@@ -101,7 +115,7 @@ static int checkout_entry(struct cache_e\n \tmemcpy(path, base_dir, len);\n \tstrcpy(path + len, ce->name);\n \n-\tif (!stat(path, &st)) {\n+\tif (!lstat(path, &st)) {\n \t\tunsigned changed = cache_match_stat(ce, &st);\n \t\tif (!changed)\n \t\t\treturn 0;\n--- a/diff-cache.c\n+++ b/diff-cache.c\n@@ -24,7 +24,7 @@ static int get_stat_data(struct cache_en\n \t\tstatic unsigned char no_sha1[20];\n \t\tint changed;\n \t\tstruct stat st;\n-\t\tif (stat(ce->name, &st) < 0)\n+\t\tif (lstat(ce->name, &st) < 0)\n \t\t\treturn -1;\n \t\tchanged = cache_match_stat(ce, &st);\n \t\tif (changed) {\n--- a/diff.c\n+++ b/diff.c\n@@ -165,7 +165,7 @@ static void prepare_temp_file(const char\n \t\t}\n \t\tstrcpy(temp->hex, sha1_to_hex(null_sha1));\n \t\tsprintf(temp->mode, \"%06o\",\n-\t\t\tS_IFREG |ce_permissions(st.st_mode));\n+\t\t\tS_IFREG | ce_permissions(st.st_mode));\n \t}\n \telse {\n \t\tint fd;\n--- a/ls-files.c\n+++ b/ls-files.c\n@@ -199,7 +199,7 @@ static void show_files(void)\n \t\t\tstruct stat st;\n \t\t\tif (excluded(ce->name) != show_ignored)\n \t\t\t\tcontinue;\n-\t\t\tif (!stat(ce->name, &st))\n+\t\t\tif (!lstat(ce->name, &st))\n \t\t\t\tcontinue;\n \t\t\tprintf(\"%s%c\", ce->name, line_terminator);\n \t\t}\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -13,6 +13,16 @@ int cache_match_stat(struct cache_entry \n {\n \tunsigned int changed = 0;\n \n+\tswitch (ntohl(ce->ce_mode) & CE_IFMASK) {\n+\tcase CE_IFREG:\n+\t\tchanged |= !S_ISREG(st->st_mode) ? TYPE_CHANGED : 0;\n+\t\tbreak;\n+\tcase CE_IFLNK:\n+\t\tchanged |= !S_ISLNK(st->st_mode) ? TYPE_CHANGED : 0;\n+\t\tbreak;\n+\tdefault:\n+\t\tdie(\"internal error: ce_mode is %o\", ntohl(ce->ce_mode));\n+\t}\n \tif (ce->ce_mtime.sec != htonl(st->st_mtime))\n \t\tchanged |= MTIME_CHANGED;\n \tif (ce->ce_ctime.sec != htonl(st->st_ctime))\n--- a/tree.c\n+++ b/tree.c\n@@ -13,7 +13,10 @@ static int read_one_entry(unsigned char \n \n \tmemset(ce, 0, size);\n \n-\tce->ce_mode = create_ce_mode(mode);\n+\tif (mode & S_IFMT)\n+\t\tce->ce_mode = htonl(mode);\n+\telse\n+\t\tce->ce_mode = create_ce_mode(mode);\n \tce->ce_flags = create_ce_flags(baselen + len, stage);\n \tmemcpy(ce->name, base, baselen);\n \tmemcpy(ce->name + baselen, pathname, len+1);\n--- a/update-cache.c\n+++ b/update-cache.c\n@@ -58,30 +58,37 @@ static int add_file_to_cache(char *path)\n \tstruct stat st;\n \tint fd;\n \n-\tfd = open(path, O_RDONLY);\n-\tif (fd < 0) {\n+\tif (lstat(path, &st) < 0) {\n \t\tif (errno == ENOENT || errno == ENOTDIR) {\n \t\t\tif (allow_remove)\n \t\t\t\treturn remove_file_from_cache(path);\n \t\t}\n \t\treturn -1;\n \t}\n-\tif (fstat(fd, &st) < 0) {\n-\t\tclose(fd);\n-\t\treturn -1;\n-\t}\n \tnamelen = strlen(path);\n \tsize = cache_entry_size(namelen);\n \tce = xmalloc(size);\n \tmemset(ce, 0, size);\n \tmemcpy(ce->name, path, namelen);\n \tfill_stat_cache_info(ce, &st);\n-\tce->ce_mode = create_ce_mode(st.st_mode);\n+\tif (S_ISREG(st.st_mode)) {\n+\t\tfd = open(path, O_RDONLY);\n+\t\tif (fd < 0)\n+\t\t\treturn -1;\n+\t\tce->ce_mode = create_ce_mode(st.st_mode);\n+\t\tif (index_fd(ce->sha1, fd, &st) < 0)\n+\t\t\treturn -1;\n+\t} else if (S_ISLNK(st.st_mode)) {\n+\t\tunsigned int len;\n+\t\tchar target[1024];\n+\t\tce->ce_mode = htonl(S_IFLNK);\n+\t\tlen = readlink(path, target, sizeof(target));\n+\t\tif (len == -1 || len+1 > sizeof(target))\n+\t\t\treturn -1;\n+\t\tif (write_sha1_file(target, len, \"blob\", ce->sha1))\n+\t\t\treturn -1;\n+\t}\n \tce->ce_flags = htons(namelen);\n-\n-\tif (index_fd(ce->sha1, fd, &st) < 0)\n-\t\treturn -1;\n-\n \treturn add_cache_entry(ce, allow_add);\n }\n \n@@ -137,7 +144,7 @@ static struct cache_entry *refresh_entry\n \tstruct cache_entry *updated;\n \tint changed, size;\n \n-\tif (stat(ce->name, &st) < 0)\n+\tif (lstat(ce->name, &st) < 0)\n \t\treturn ERR_PTR(-errno);\n \n \tchanged = cache_match_stat(ce, &st);\n@@ -145,10 +152,10 @@ static struct cache_entry *refresh_entry\n \t\treturn ce;\n \n \t/*\n-\t * If the mode has changed, there's no point in trying\n+\t * If the mode or type has changed, there's no point in trying\n \t * to refresh the entry - it's not going to match\n \t */\n-\tif (changed & MODE_CHANGED)\n+\tif (changed & (MODE_CHANGED | TYPE_CHANGED))\n \t\treturn ERR_PTR(-EINVAL);\n \n \tif (compare_data(ce, st.st_size))\n\n"},{"id":"2607","messageId":"7vy8aul8rs.fsf@assigned-by-dhcp.cox.net","threadId":"460","inReplyTo":"20050505012051.GA26201@vrfy.org","subject":"Re: git and symlinks as tracked content","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-05T02:13:43Z","receivedAt":"2005-05-05T02:13:43Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"KS\" == Kay Sievers <kay.sievers@vrfy.org> writes:\n\n>> * It continues to assume that S_IFREG, S_IFDIR and S_IFLNK have\n>> the same bit pattern everywhere....\n\n>> * read-cache.c:cache_match_stat() ...\n\nKS> Both included and updated.\n\nThe second one, yes, but the first one is \"not really\".  If you\nare going to do this:\n\nKS> +#define CE_IFREG  0100000\nKS> +#define CE_IFDIR  0040000\nKS> ...\nKS> +#define CE_IFMASK 0770000\n \nthen you need to touch these things:\n\nKS> +\tmode = ntohl(ce->ce_mode);\nKS> +\tif (S_ISLNK(mode)) {\n\nHere mode encodes type in CE_ format, so S_ISLNK() is bad.\n\nKS> @@ -165,7 +165,7 @@ static void prepare_temp_file(const char\nKS>  \t\t}\nKS>  \t\tstrcpy(temp->hex, sha1_to_hex(null_sha1));\nKS>  \t\tsprintf(temp->mode, \"%06o\",\nKS> -\t\t\tS_IFREG |ce_permissions(st.st_mode));\nKS> +\t\t\tS_IFREG | ce_permissions(st.st_mode));\nKS>  \t}\n\nLikewise here, although this is my bad.  I did not know if you\nare going to take CE_ type suggestion so I left it as it was.\n\nThere are more.  \"grep 'S_I[SF]' *.[ch] */*.[ch]\" would tell us\nmost if not all.  We probably would want to have CE_ISLNK() and\nfriends, parallel to S_ISLNK() and friends if we go this route.\n\nDoes POSIX or something have nice to say that we do not have to\nworry about this?  Or are the stat type bits really different on\ndifferent Unixen?  I used to do porting for living across a\ndozen or so different Unixen long time ago and I should know the\nanswer to this kind of thing by heart, but I do not anymore X-<.\n\n"},{"id":"2611","messageId":"200505050709.43307.alan@chandlerfamily.org.uk","threadId":"460","inReplyTo":"Pine.LNX.4.21.0505041854040.30848-100000@iabervon.org","subject":"Re: git and symlinks as tracked content","fromName":"Alan Chandler","fromEmail":"alan@chandlerfamily.org.uk","sentAt":"2005-05-05T06:09:43Z","receivedAt":"2005-05-05T06:09:43Z","isPatch":false,"sender":{"key":"alan@chandlerfamily.org.uk","avatar":"https://gravatar.com/avatar/1862247e5ea8eac114c842f9dc3a5db6253754e24ef7171757cf97eedce48b8c?d=mp&s=160"},"body":"On Thursday 05 May 2005 00:03, Daniel Barkalow wrote:\n\n> (on the other hand, it might make sense for git to handle files starting\n> with '.', and only skip .git).\n\ndefinitely only as an option.  I envisage checking out (maybe anonymously) \nfrom svn or other repositories and then using git locally to manage my own \ndevelopment.  It would be preferable for the .git repository not to be \n\"polluted\" with the svn prisine trees etc \n\n\n-- \nAlan Chandler\nhttp://www.chandlerfamily.org.uk\n"},{"id":"2614","messageId":"Pine.LNX.4.62.0505050231300.15451@qynat.qvtvafvgr.pbz","threadId":"460","inReplyTo":"200505050709.43307.alan@chandlerfamily.org.uk","subject":"read-only git repositories","fromName":"David Lang","fromEmail":"david.lang@digitalinsight.com","sentAt":"2005-05-05T09:51:50Z","receivedAt":"2005-05-05T09:51:50Z","isPatch":false,"sender":{"key":"david.lang@digitalinsight.com","avatar":null},"body":"given that git already treats everything in the object storage as being \nfixed it occured to me that there may be value in makeing it so that git \ncan make use of more then one pool of storage.\n\npossible uses of this would be to have a bunch of data on read-only media \n(say the 3G+ kernel history on a DVD), having a pruned local object store \nwith automated fetching from elsewhere if the object isn't found locally, \nor marking the object store that you plan on sharing with the world as \nread-only (with your changed object going into a secondary store) so that \nyou don't pollute it accidently (this could also cut down on the storage \nrequirements)\n\nthere are probably other uses and it seems like a fairly small \nmodification to add a hook to use if the object isn't found initially that \nI thought I'd mention it to the group.\n\nDavid Lang\n\n-- \nThere are two ways of constructing a software design. One way is to make it so simple that there are obviously no deficiencies. And the other way is to make it so complicated that there are no obvious deficiencies.\n  -- C.A.R. Hoare\n"},{"id":"2617","messageId":"20050505123825.GA30156@vrfy.org","threadId":"460","inReplyTo":"7vy8aul8rs.fsf@assigned-by-dhcp.cox.net","subject":"Re: git and symlinks as tracked content","fromName":"Kay Sievers","fromEmail":"kay.sievers@vrfy.org","sentAt":"2005-05-05T12:38:25Z","receivedAt":"2005-05-05T12:38:25Z","isPatch":false,"sender":{"key":"kay.sievers@vrfy.org","avatar":null},"body":"Allow to store and track symlink in the repository. A symlink is stored\nthe same way as a regular file, only with the appropriate mode bits set.\nThe symlink target is therefore stored in a blob object.\nThis will hopefully make our udev repository fully functional. :)\n\nSigned-off-by: Kay Sievers <kay.sievers@vrfy.org>\n---\n\nOn Wed, May 04, 2005 at 07:13:43PM -0700, Junio C Hamano wrote:\n> >>>>> \"KS\" == Kay Sievers <kay.sievers@vrfy.org> writes:\n\n> I did not know if you are going to take CE_ type suggestion so \n> I left it as it was.\n> \n> There are more.  \"grep 'S_I[SF]' *.[ch] */*.[ch]\" would tell us\n> most if not all.  We probably would want to have CE_ISLNK() and\n> friends, parallel to S_ISLNK() and friends if we go this route.\n\nHmm, how about this?\n\nThanks,\nKay\n\n--- a/cache.h\n+++ b/cache.h\n@@ -87,7 +87,14 @@ struct cache_entry {\n #define ce_stage(ce) ((CE_STAGEMASK & ntohs((ce)->ce_flags)) >> CE_STAGESHIFT)\n \n #define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644)\n-#define create_ce_mode(mode) htonl(S_IFREG | ce_permissions(mode))\n+static inline unsigned int create_ce_mode(unsigned int mode)\n+{\n+\tif (S_ISREG(mode))\n+\t\treturn htonl(S_IFREG | ce_permissions(mode));\n+\tif (S_ISLNK(mode))\n+\t\treturn htonl(S_IFLNK);\n+\treturn htonl(mode);\n+}\n \n #define cache_entry_size(len) ((offsetof(struct cache_entry,name) + (len) + 8) & ~7)\n \n@@ -124,6 +131,7 @@ extern int index_fd(unsigned char *sha1,\n #define MODE_CHANGED    0x0008\n #define INODE_CHANGED   0x0010\n #define DATA_CHANGED    0x0020\n+#define TYPE_CHANGED    0x0040\n \n /* Return a statically allocated filename matching the sha1 signature */\n extern char *sha1_file_name(const unsigned char *sha1);\n--- a/check-files.c\n+++ b/check-files.c\n@@ -28,8 +28,8 @@ static void check_file(const char *path)\n \t\tdie(\"preparing to update existing file '%s' not in cache\", path);\n \tce = active_cache[pos];\n \n-\tif (fstat(fd, &st) < 0)\n-\t\tdie(\"fstat(%s): %s\", path, strerror(errno));\n+\tif (lstat(path, &st) < 0)\n+\t\tdie(\"lstat(%s): %s\", path, strerror(errno));\n \n \tchanged = cache_match_stat(ce, &st);\n \tif (changed)\n--- a/checkout-cache.c\n+++ b/checkout-cache.c\n@@ -72,23 +72,41 @@ static int write_entry(struct cache_entr\n \tunsigned long size;\n \tlong wrote;\n \tchar type[20];\n+\tchar target[1024];\n \n \tnew = read_sha1_file(ce->sha1, type, &size);\n \tif (!new || strcmp(type, \"blob\")) {\n \t\treturn error(\"checkout-cache: unable to read sha1 file of %s (%s)\",\n \t\t\tpath, sha1_to_hex(ce->sha1));\n \t}\n-\tfd = create_file(path, ntohl(ce->ce_mode));\n-\tif (fd < 0) {\n+\tswitch (ntohl(ce->ce_mode) & S_IFMT) {\n+\tcase S_IFREG:\n+\t\tfd = create_file(path, ntohl(ce->ce_mode));\n+\t\tif (fd < 0) {\n+\t\t\tfree(new);\n+\t\t\treturn error(\"checkout-cache: unable to create file %s (%s)\",\n+\t\t\t\tpath, strerror(errno));\n+\t\t}\n+\t\twrote = write(fd, new, size);\n+\t\tclose(fd);\n+\t\tfree(new);\n+\t\tif (wrote != size)\n+\t\t\treturn error(\"checkout-cache: unable to write file %s\", path);\n+\t\tbreak;\n+\tcase S_IFLNK:\n+\t\tmemcpy(target, new, size);\n+\t\ttarget[size] = '\\0';\n+\t\tif (symlink(target, path)) {\n+\t\t\tfree(new);\n+\t\t\treturn error(\"checkout-cache: unable to create symlink %s (%s)\",\n+\t\t\t\tpath, strerror(errno));\n+\t\t}\n+\t\tfree(new);\n+\t\tbreak;\n+\tdefault:\n \t\tfree(new);\n-\t\treturn error(\"checkout-cache: unable to create %s (%s)\",\n-\t\t\tpath, strerror(errno));\n+\t\treturn error(\"checkout-cache: unknown file mode for %s\", path);\n \t}\n-\twrote = write(fd, new, size);\n-\tclose(fd);\n-\tfree(new);\n-\tif (wrote != size)\n-\t\treturn error(\"checkout-cache: unable to write %s\", path);\n \treturn 0;\n }\n \n@@ -101,7 +119,7 @@ static int checkout_entry(struct cache_e\n \tmemcpy(path, base_dir, len);\n \tstrcpy(path + len, ce->name);\n \n-\tif (!stat(path, &st)) {\n+\tif (!lstat(path, &st)) {\n \t\tunsigned changed = cache_match_stat(ce, &st);\n \t\tif (!changed)\n \t\t\treturn 0;\n--- a/diff-cache.c\n+++ b/diff-cache.c\n@@ -24,7 +24,7 @@ static int get_stat_data(struct cache_en\n \t\tstatic unsigned char no_sha1[20];\n \t\tint changed;\n \t\tstruct stat st;\n-\t\tif (stat(ce->name, &st) < 0)\n+\t\tif (lstat(ce->name, &st) < 0)\n \t\t\treturn -1;\n \t\tchanged = cache_match_stat(ce, &st);\n \t\tif (changed) {\n--- a/ls-files.c\n+++ b/ls-files.c\n@@ -199,7 +199,7 @@ static void show_files(void)\n \t\t\tstruct stat st;\n \t\t\tif (excluded(ce->name) != show_ignored)\n \t\t\t\tcontinue;\n-\t\t\tif (!stat(ce->name, &st))\n+\t\t\tif (!lstat(ce->name, &st))\n \t\t\t\tcontinue;\n \t\t\tprintf(\"%s%c\", ce->name, line_terminator);\n \t\t}\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -13,6 +13,16 @@ int cache_match_stat(struct cache_entry \n {\n \tunsigned int changed = 0;\n \n+\tswitch (ntohl(ce->ce_mode) & S_IFMT) {\n+\tcase S_IFREG:\n+\t\tchanged |= !S_ISREG(st->st_mode) ? TYPE_CHANGED : 0;\n+\t\tbreak;\n+\tcase S_IFLNK:\n+\t\tchanged |= !S_ISLNK(st->st_mode) ? TYPE_CHANGED : 0;\n+\t\tbreak;\n+\tdefault:\n+\t\tdie(\"internal error: ce_mode is %o\", ntohl(ce->ce_mode));\n+\t}\n \tif (ce->ce_mtime.sec != htonl(st->st_mtime))\n \t\tchanged |= MTIME_CHANGED;\n \tif (ce->ce_ctime.sec != htonl(st->st_ctime))\n--- a/update-cache.c\n+++ b/update-cache.c\n@@ -57,19 +57,16 @@ static int add_file_to_cache(char *path)\n \tstruct cache_entry *ce;\n \tstruct stat st;\n \tint fd;\n+\tunsigned int len;\n+\tchar target[1024];\n \n-\tfd = open(path, O_RDONLY);\n-\tif (fd < 0) {\n+\tif (lstat(path, &st) < 0) {\n \t\tif (errno == ENOENT || errno == ENOTDIR) {\n \t\t\tif (allow_remove)\n \t\t\t\treturn remove_file_from_cache(path);\n \t\t}\n \t\treturn -1;\n \t}\n-\tif (fstat(fd, &st) < 0) {\n-\t\tclose(fd);\n-\t\treturn -1;\n-\t}\n \tnamelen = strlen(path);\n \tsize = cache_entry_size(namelen);\n \tce = xmalloc(size);\n@@ -78,10 +75,24 @@ static int add_file_to_cache(char *path)\n \tfill_stat_cache_info(ce, &st);\n \tce->ce_mode = create_ce_mode(st.st_mode);\n \tce->ce_flags = htons(namelen);\n-\n-\tif (index_fd(ce->sha1, fd, &st) < 0)\n+\tswitch (st.st_mode & S_IFMT) {\n+\tcase S_IFREG:\n+\t\tfd = open(path, O_RDONLY);\n+\t\tif (fd < 0)\n+\t\t\treturn -1;\n+\t\tif (index_fd(ce->sha1, fd, &st) < 0)\n+\t\t\treturn -1;\n+\t\tbreak;\n+\tcase S_IFLNK:\n+\t\tlen = readlink(path, target, sizeof(target));\n+\t\tif (len == -1 || len+1 > sizeof(target))\n+\t\t\treturn -1;\n+\t\tif (write_sha1_file(target, len, \"blob\", ce->sha1))\n+\t\t\treturn -1;\n+\t\tbreak;\n+\tdefault:\n \t\treturn -1;\n-\n+\t}\n \treturn add_cache_entry(ce, allow_add);\n }\n \n@@ -137,7 +148,7 @@ static struct cache_entry *refresh_entry\n \tstruct cache_entry *updated;\n \tint changed, size;\n \n-\tif (stat(ce->name, &st) < 0)\n+\tif (lstat(ce->name, &st) < 0)\n \t\treturn ERR_PTR(-errno);\n \n \tchanged = cache_match_stat(ce, &st);\n@@ -145,10 +156,10 @@ static struct cache_entry *refresh_entry\n \t\treturn ce;\n \n \t/*\n-\t * If the mode has changed, there's no point in trying\n+\t * If the mode or type has changed, there's no point in trying\n \t * to refresh the entry - it's not going to match\n \t */\n-\tif (changed & MODE_CHANGED)\n+\tif (changed & (MODE_CHANGED | TYPE_CHANGED))\n \t\treturn ERR_PTR(-EINVAL);\n \n \tif (compare_data(ce, st.st_size))\n\n"},{"id":"2618","messageId":"3018.10.10.10.24.1115296752.squirrel@linux1","threadId":"460","inReplyTo":"Pine.LNX.4.62.0505050231300.15451@qynat.qvtvafvgr.pbz","subject":"Re: read-only git repositories","fromName":"Sean","fromEmail":"seanlkml@sympatico.ca","sentAt":"2005-05-05T12:39:12Z","receivedAt":"2005-05-05T12:39:12Z","isPatch":false,"sender":{"key":"seanlkml@sympatico.ca","avatar":"https://gravatar.com/avatar/f92923f54fc08c401fc59b71829d4b89e9b8087fbba45ff87c82e6a83aee02ae?d=mp&s=160"},"body":"On Thu, May 5, 2005 5:51 am, David Lang said:\n\n> there are probably other uses and it seems like a fairly small\n> modification to add a hook to use if the object isn't found initially\n> that I thought I'd mention it to the group.\n>\nDavid,\n\nGreat idea!  This seems like an option that naturally falls out of the git\ndesign.  You're right that there are lots of uses for it too; another\nwould be to keep all local changes in an isolated object store for backup\netc.\n\nSean\n\n\n"},{"id":"2636","messageId":"Pine.LNX.4.21.0505051715500.30848-100000@iabervon.org","threadId":"460","inReplyTo":"200505050709.43307.alan@chandlerfamily.org.uk","subject":"Re: git and symlinks as tracked content","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-05-05T21:23:22Z","receivedAt":"2005-05-05T21:23:22Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Thu, 5 May 2005, Alan Chandler wrote:\n\n> On Thursday 05 May 2005 00:03, Daniel Barkalow wrote:\n> \n> > (on the other hand, it might make sense for git to handle files starting\n> > with '.', and only skip .git).\n> \n> definitely only as an option.  I envisage checking out (maybe anonymously) \n> from svn or other repositories and then using git locally to manage my own \n> development.  It would be preferable for the .git repository not to be \n> \"polluted\" with the svn prisine trees etc \n\nIt wouldn't touch them at all unless you specifically added them. The\npresent situation is that git ignores files starting with \".\" even if you\nspecifically add them.\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"},{"id":"2650","messageId":"427ADDEC.3060709@dwheeler.com","threadId":"460","inReplyTo":"Pine.LNX.4.62.0505050231300.15451@qynat.qvtvafvgr.pbz","subject":"Re: read-only git repositories (ancient history)","fromName":"David A. Wheeler","fromEmail":"dwheeler@dwheeler.com","sentAt":"2005-05-06T03:01:00Z","receivedAt":"2005-05-06T03:01:00Z","isPatch":false,"sender":{"key":"dwheeler@dwheeler.com","avatar":"https://avatars.githubusercontent.com/u/813150?v=4"},"body":"David Lang wrote:\n> given that git already treats everything in the object storage as being \n> fixed it occured to me that there may be value in makeing it so that git \n> can make use of more then one pool of storage\n...\n> there are probably other uses and it seems like a fairly small \n> modification to add a hook to use if the object isn't found initially \n> that I thought I'd mention it to the group.\n\nReasonable.  Another use would be to have a repository with\n\"ancient history\" (e.g., Linux pre-2.6) that isn't normally\nloaded or looked at, but COULD be looked at if you added\nthat repository.  For that use, though, you'd need a way to\nrecord \"the parent of X is Y\" since the information creating\nconnections BETWEEN the repositories might not be stored in\nthe later repository itself (see the discussions about Linux kernel\nhistory recreation).\n\n--- David A. Wheeler\n"}]}