I was thinking about puting my /etc in SVN or CVS but then I got to thinking about git? Has anyone ever tried to version their /ect with git?
--adam
I was thinking about puting my /etc in SVN or CVS but then I got to thinking about git? Has anyone ever tried to version their /ect with git?
--adam
Re: /etc in git?
Adam Hunt <kinema@gmail.com> writes:
> ... Has anyone ever tried to version their /ect with > git?
Yes.
Re: /etc in git?
Do you have any more details by chance? Does it work? Does it work well? How does one do it?
--adam
On 1/18/06, Junio C Hamano <junkio@cox.net> wrote:
> Adam Hunt <kinema@gmail.com> writes: > > > ... Has anyone ever tried to version their /ect with > > git? > > Yes. > >
Re: /etc in git?
Adam Hunt wrote:
> Do you have any more details by chance? Does it work? Does it work > well? How does one do it?
I've put my home directory dot files into git, and I'm assuming it's going to be a similar issue for /etc. I've found git to be unusually suitable for this, for the following reasons:
- git can deal with only managing a handful of files from a large hierarchy, without an insane performance penalty. - git only needs one repository directory at the root of the tree, not in each subdirectory.
The biggest *problem* with git is that it doesn't handle files which need to have their permissions maintained.
-hpa
Re: /etc in git?
Adam Hunt <kinema@gmail.com> writes:
> Do you have any more details by chance? Does it work? Does it work > well? How does one do it?
I personally feel it is a horrible and stupid thing to do, if by "version control /etc" you mean to have /.git which controls /etc/hosts and stuff in place. It would work (git does not refuse to run as root). But being a *source* control system, we deliberately refuse to store the full permission bits, so if your /etc/shadow is mode 0600 while /etc/hosts is mode 0644, you have to make sure they stay that way after checking things out.
You are much better off to keep /usr/src/rootstuff/.git (and working tree files are /usr/src/rootstuff/etc/hosts and friends), have a build procedure (read: Makefile) there, and version control that source directory. I usually have 'install' and 'diff' target in that Makefile, so that I can do this:
$ cd /usr/src/rootstuff
$ make diff ;# to see if somebody edited any targets by hand
$ edit etc/hosts
$ git diff ;# to see the source change
$ make diff ;# to see the change I am going to install
$ su
# make install; exit
$ git commit -a -m 'Add a new host.'Being able to run "diff" before actually doing it is very handy and useful safety/sanity measure.
Obviously, /usr/src/rootstuff/ should be mode 0770 or stricter, owned by the operator group; it would contain some sensitive information.
Re: /etc in git?
Junio C Hamano wrote:
> Adam Hunt <kinema@gmail.com> writes: > > >>Do you have any more details by chance? Does it work? Does it work >>well? How does one do it? > > > I personally feel it is a horrible and stupid thing to do, if by > "version control /etc" you mean to have /.git which controls > /etc/hosts and stuff in place. It would work (git does not > refuse to run as root). But being a *source* control system, we > deliberately refuse to store the full permission bits, so if > your /etc/shadow is mode 0600 while /etc/hosts is mode 0644, you > have to make sure they stay that way after checking things out.
This is, admittedly, a major problem.
If you instead take the viewpoint that the /etc/.git/ repository is for tracking textual diffs and not for serving as a backup, it should be an acceptable tool however. In my opinion, to be truly useful, it would need to also automatically commit changes during package installation, upgrade, and removal. (To be incredibly useful, it would 3-way merge changes. That, I think, is a fantasy at this time.)
> > You are much better off to keep /usr/src/rootstuff/.git (and > working tree files are /usr/src/rootstuff/etc/hosts and > friends), have a build procedure (read: Makefile) there, and > version control that source directory. I usually have 'install' > and 'diff' target in that Makefile, so that I can do this: > > $ cd /usr/src/rootstuff > $ make diff ;# to see if somebody edited any targets by hand > $ edit etc/hosts > $ git diff ;# to see the source change > $ make diff ;# to see the change I am going to install > $ su > # make install; exit > $ git commit -a -m 'Add a new host.' > > Being able to run "diff" before actually doing it is very handy > and useful safety/sanity measure. > > Obviously, /usr/src/rootstuff/ should be mode 0770 or stricter, > owned by the operator group; it would contain some sensitive > information.
If you're doing this, especially if you're doing this on multiple machines, creating a package is probably a worthwhile thing to contemplate as well.
Re: /etc in git?
Ryan Anderson <ryan@michonline.com> writes:
> Junio C Hamano wrote: >> Adam Hunt <kinema@gmail.com> writes: >> >> >>>Do you have any more details by chance? Does it work? Does it work >>>well? How does one do it? >> >> >> I personally feel it is a horrible and stupid thing to do, if by >> "version control /etc" you mean to have /.git which controls >> /etc/hosts and stuff in place. It would work (git does not >> refuse to run as root). But being a *source* control system, we >> deliberately refuse to store the full permission bits, so if >> your /etc/shadow is mode 0600 while /etc/hosts is mode 0644, you >> have to make sure they stay that way after checking things out. > > This is, admittedly, a major problem.
An SCM is not a replacement of a backup.
>> You are much better off to keep /usr/src/rootstuff/.git (and >> working tree files are /usr/src/rootstuff/etc/hosts and >> friends), have a build procedure (read: Makefile) there, and >> version control that source directory. I usually have 'install' >> and 'diff' target in that Makefile, so that I can do this: >>... > If you're doing this, especially if you're doing this on multiple > machines, creating a package is probably a worthwhile thing to > contemplate as well.
In my workplace environment, the equivalent of the above /usr/src/rootstuff is accessible throughout the networked machines (mostly NFS mounted); for things that needs per-host customization, we do not have /usr/src/rootstuff/etc/hosts but keep /usr/src/rootstuff/etc/hosts.in as the source, and Makefile customizes that into a form suitable for installation for each machine. Especially useful is vfstab.in --- a single source builds fstab for local mounting and nfs exports, while other machines have mountpoints and project symlinks pointing into location automounted from that machine with disk, generated automatically. This does not match typical "package" use.
[PATCH] Support precise tracking of file modes
Dear diary, on Thu, Jan 19, 2006 at 08:50:22AM CET, I got a letter where Junio C Hamano <junkio@cox.net> said that...
> Ryan Anderson <ryan@michonline.com> writes: > > > Junio C Hamano wrote: > >> Adam Hunt <kinema@gmail.com> writes: > >> > >> > >>>Do you have any more details by chance? Does it work? Does it work > >>>well? How does one do it? > >> > >> > >> I personally feel it is a horrible and stupid thing to do, if by > >> "version control /etc" you mean to have /.git which controls > >> /etc/hosts and stuff in place. It would work (git does not > >> refuse to run as root). But being a *source* control system, we > >> deliberately refuse to store the full permission bits, so if > >> your /etc/shadow is mode 0600 while /etc/hosts is mode 0644, you > >> have to make sure they stay that way after checking things out. > > > > This is, admittedly, a major problem. > > An SCM is not a replacement of a backup.
It seems that this is mostly an artificial imposition and it's annoying. Hey, I need to leave for an exam in 15 minutes and I have few urgent items in my Cogito TODO (sorry, Pavel!), but I couldn't resist.
Taking "quick'n'dirty" to the extreme _and_ combining it with Linus' attitude to testing and documentation... ;-)
diff --git a/cache.h b/cache.h index 29c9e81..0311066 100644 --- a/cache.h +++ b/cache.h @@ -94,7 +94,9 @@ struct cache_entry { #define ce_size(ce) cache_entry_size(ce_namelen(ce)) #define ce_stage(ce) ((CE_STAGEMASK & ntohs((ce)->ce_flags)) >> CE_STAGESHIFT) -#define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644) +extern int track_filemode; + +#define ce_permissions(mode) (track_filemode ? (mode) : (((mode) & 0100) ? 0755 : 0644)) static inline unsigned int create_ce_mode(unsigned int mode) { if (S_ISLNK(mode)) diff --git a/checkout-index.c b/checkout-index.c index 53dd8cb..b073baa 100644 --- a/checkout-index.c +++ b/checkout-index.c @@ -115,6 +115,8 @@ int main(int argc, char **argv) int newfd = -1; int all = 0; + git_config(git_default_config); + prefix = setup_git_directory(); prefix_length = prefix ? strlen(prefix) : 0; diff --git a/config.c b/config.c index 8355224..a92ee0f 100644 --- a/config.c +++ b/config.c @@ -222,6 +222,11 @@ int git_default_config(const char *var, return 0; } + if (!strcmp(var, "core.trackallfilemodes")) { + track_filemode = git_config_bool(var, value); + return 0; + } + if (!strcmp(var, "core.symrefsonly")) { only_use_symrefs = git_config_bool(var, value); return 0; diff --git a/entry.c b/entry.c index 410b758..493f2b9 100644 --- a/entry.c +++ b/entry.c @@ -87,6 +87,11 @@ static int write_entry(struct cache_entr return error("git-checkout-index: unable to create file %s (%s)", path, strerror(errno)); } + if (track_filemode) { + if (fchmod(fd, ntohl(ce->ce_mode)) < 0) + return error("git-checkout-index: unable to chmod file %s (%s)", + path, strerror(errno)); + } wrote = write(fd, new, size); close(fd); free(new); diff --git a/environment.c b/environment.c index 0596fc6..53248ec 100644 --- a/environment.c +++ b/environment.c @@ -12,6 +12,7 @@ char git_default_email[MAX_GITNAME]; char git_default_name[MAX_GITNAME]; int trust_executable_bit = 1; +int track_filemode = 0; int only_use_symrefs = 0; int repository_format_version = 0; char git_commit_encoding[MAX_ENCODING_LENGTH] = "utf-8"; diff --git a/fsck-objects.c b/fsck-objects.c index 90e638e..719add2 100644 --- a/fsck-objects.c +++ b/fsck-objects.c @@ -174,7 +174,8 @@ static int fsck_tree(struct tree *item) if (!check_strict) break; default: - has_bad_modes = 1; + if (!track_filemode || (entry->mode & ~(S_IFREG|0777))) + has_bad_modes = 1; } if (last) { diff --git a/read-cache.c b/read-cache.c index c5474d4..624d2c3 100644 --- a/read-cache.c +++ b/read-cache.c @@ -98,7 +98,7 @@ static int ce_match_stat_basic(struct ca * "mode changes" */ if (trust_executable_bit && - (0100 & (ntohl(ce->ce_mode) ^ st->st_mode))) + ((track_filemode ? 0777 : 0100) & (ntohl(ce->ce_mode) ^ st->st_mode))) changed |= MODE_CHANGED; break; case S_IFLNK:
-- Petr "Pasky" Baudis Stuff: http://pasky.or.cz/ Of the 3 great composers Mozart tells us what it's like to be human, Beethoven tells us what it's like to be Beethoven and Bach tells us what it's like to be the universe. -- Douglas Adams
Re: [PATCH] Support precise tracking of file modes
Petr Baudis <pasky@suse.cz> writes:
> Taking "quick'n'dirty" to the extreme _and_ combining it with Linus' > attitude to testing and documentation... ;-)
It is premature for us mere mortals to imitate Linus in that aspect by at least ten years ;-). Please don't.
About the content of the change, if we were to do this, we need to also record owner and group. recording full permissions without recording owner and group does not make much sense.
Re: [PATCH] Support precise tracking of file modes
Dear diary, on Thu, Jan 19, 2006 at 07:25:03PM CET, I got a letter where Junio C Hamano <junkio@cox.net> said that...
> Petr Baudis <pasky@suse.cz> writes: > > > Taking "quick'n'dirty" to the extreme _and_ combining it with Linus' > > attitude to testing and documentation... ;-) > > It is premature for us mere mortals to imitate Linus in that > aspect by at least ten years ;-). Please don't.
Yes, it was really just kind of proof-of-concept patch.
> About the content of the change, if we were to do this, we need > to also record owner and group. recording full permissions > without recording owner and group does not make much sense.
This would require much larger changes to the tree structure while we can get this essentially for free and I believe it covers most of the usage scenarios. In my /etc, all but two files are owned by root.root, and in my ~, all the dot-files are owned by pasky.users, while the permissions are a lot more varied.
-- Petr "Pasky" Baudis Stuff: http://pasky.or.cz/ Of the 3 great composers Mozart tells us what it's like to be human, Beethoven tells us what it's like to be Beethoven and Bach tells us what it's like to be the universe. -- Douglas Adams
Re: [PATCH] Support precise tracking of file modes
On 1/19/06, Junio C Hamano <junkio@cox.net> wrote:
> Petr Baudis <pasky@suse.cz> writes: > > > Taking "quick'n'dirty" to the extreme _and_ combining it with Linus' > > attitude to testing and documentation... ;-) > > It is premature for us mere mortals to imitate Linus in that > aspect by at least ten years ;-). Please don't. > > About the content of the change, if we were to do this, we need > to also record owner and group. recording full permissions > without recording owner and group does not make much sense. >
Maybe implement tracking of a generic file attribute would be a better idea? So that porcellans can implement permissions/ownership/EA themselves, if they really want to...
Re: [PATCH] Support precise tracking of file modes
2006/1/19, Petr Baudis <pasky@suse.cz>:
> It seems that this is mostly an artificial imposition and it's annoying.
> Hey, I need to leave for an exam in 15 minutes and I have few urgent
> items in my Cogito TODO (sorry, Pavel!), but I couldn't resist.
>
> Taking "quick'n'dirty" to the extreme _and_ combining it with Linus'
> attitude to testing and documentation... ;-)
>
> diff --git a/cache.h b/cache.h
> index 29c9e81..0311066 100644
> --- a/cache.h
> +++ b/cache.h
> @@ -94,7 +94,9 @@ struct cache_entry {
> #define ce_size(ce) cache_entry_size(ce_namelen(ce))
> #define ce_stage(ce) ((CE_STAGEMASK & ntohs((ce)->ce_flags)) >> CE_STAGESHIFT)
>
> -#define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644)
> +extern int track_filemode;
> +
> +#define ce_permissions(mode) (track_filemode ? (mode) : (((mode) & 0100) ? 0755 : 0644))
> static inline unsigned int create_ce_mode(unsigned int mode)
> {
> if (S_ISLNK(mode))
> diff --git a/checkout-index.c b/checkout-index.c
> index 53dd8cb..b073baa 100644
> --- a/checkout-index.c
> +++ b/checkout-index.c
> @@ -115,6 +115,8 @@ int main(int argc, char **argv)
> int newfd = -1;
> int all = 0;
>
> + git_config(git_default_config);
> +
> prefix = setup_git_directory();
> prefix_length = prefix ? strlen(prefix) : 0;
>
> diff --git a/config.c b/config.c
> index 8355224..a92ee0f 100644
> --- a/config.c
> +++ b/config.c
> @@ -222,6 +222,11 @@ int git_default_config(const char *var,
> return 0;
> }
>
> + if (!strcmp(var, "core.trackallfilemodes")) {
> + track_filemode = git_config_bool(var, value);
> + return 0;
> + }
> +
> if (!strcmp(var, "core.symrefsonly")) {
> only_use_symrefs = git_config_bool(var, value);
> return 0;
> diff --git a/entry.c b/entry.c
> index 410b758..493f2b9 100644
> --- a/entry.c
> +++ b/entry.c
> @@ -87,6 +87,11 @@ static int write_entry(struct cache_entr
> return error("git-checkout-index: unable to create file %s (%s)",
> path, strerror(errno));
> }
> + if (track_filemode) {
> + if (fchmod(fd, ntohl(ce->ce_mode)) < 0)
> + return error("git-checkout-index: unable to chmod file %s (%s)",
> + path, strerror(errno));
> + }
> wrote = write(fd, new, size);
> close(fd);
> free(new);
> diff --git a/environment.c b/environment.c
> index 0596fc6..53248ec 100644
> --- a/environment.c
> +++ b/environment.c
> @@ -12,6 +12,7 @@
> char git_default_email[MAX_GITNAME];
> char git_default_name[MAX_GITNAME];
> int trust_executable_bit = 1;
> +int track_filemode = 0;
> int only_use_symrefs = 0;
> int repository_format_version = 0;
> char git_commit_encoding[MAX_ENCODING_LENGTH] = "utf-8";
> diff --git a/fsck-objects.c b/fsck-objects.c
> index 90e638e..719add2 100644
> --- a/fsck-objects.c
> +++ b/fsck-objects.c
> @@ -174,7 +174,8 @@ static int fsck_tree(struct tree *item)
> if (!check_strict)
> break;
> default:
> - has_bad_modes = 1;
> + if (!track_filemode || (entry->mode & ~(S_IFREG|0777)))
> + has_bad_modes = 1;
> }
>
> if (last) {
> diff --git a/read-cache.c b/read-cache.c
> index c5474d4..624d2c3 100644
> --- a/read-cache.c
> +++ b/read-cache.c
> @@ -98,7 +98,7 @@ static int ce_match_stat_basic(struct ca
> * "mode changes"
> */
> if (trust_executable_bit &&
> - (0100 & (ntohl(ce->ce_mode) ^ st->st_mode)))
> + ((track_filemode ? 0777 : 0100) & (ntohl(ce->ce_mode) ^ st->st_mode)))
> changed |= MODE_CHANGED;
> break;
> case S_IFLNK:
>
>
> --
> Petr "Pasky" BaudisI didn't test the patch, but the feature the patch tries to implement is really something I'm missing from git (or any other scm I know of). Ideally, this will be combined with exact owner tracking, but exact permission and/or owner handling should be activated independently per repository.
Peter Baumann
Re: /etc in git?
Junio C Hamano wrote:
>Ryan Anderson <ryan@michonline.com> writes: > > >>Junio C Hamano wrote: >> >> >>>You are much better off to keep /usr/src/rootstuff/.git (and >>>working tree files are /usr/src/rootstuff/etc/hosts and >>>friends), have a build procedure (read: Makefile) there, and >>>version control that source directory. I usually have 'install' >>>and 'diff' target in that Makefile, so that I can do this: >>>... >>> >>> >>If you're doing this, especially if you're doing this on multiple >>machines, creating a package is probably a worthwhile thing to >>contemplate as well. >> >> > >In my workplace environment, the equivalent of the above >/usr/src/rootstuff is accessible throughout the networked >machines (mostly NFS mounted); for things that needs per-host >customization, we do not have /usr/src/rootstuff/etc/hosts but >keep /usr/src/rootstuff/etc/hosts.in as the source, and Makefile >customizes that into a form suitable for installation for each >machine. Especially useful is vfstab.in --- a single source >builds fstab for local mounting and nfs exports, while other >machines have mountpoints and project symlinks pointing into >location automounted from that machine with disk, generated >automatically. This does not match typical "package" use. > >
To provide an off-topic, but perhaps useful, counter-example, where I work, I've made a package that does something similar.
I use a Makefile to generate a few template files, such as /etc/resolv.conf, /etc/apt/preferences, /etc/sudoers, /etc/ntp.conf It Pre-Depends on, ntp, sudo, (etc).
A postinstallation script does a little bit of tweaking of these files based upon the answers to one or two questions asked during installation.
It's simply another way of looking at the problem.
-- Ryan Anderson sometimes Pug Majere
Re: /etc in git?
Ryan Anderson <ryan@michonline.com> writes:
>>... This does not match typical "package" use. >> > To provide an off-topic, but perhaps useful, counter-example, where I > work, I've made a package that does something similar...
Ah, haven't thought about the use of postinstallation scripts. If your environment is more or less uniform that is an excellent way of doing it.
Unfortunately, our Solaris boxen do not understand .deb postinst scripts, so that is why we are not doing it X-<. Maybe after we get rid of them perhaps..
Re: /etc in git?
On Wed, Jan 18, 2006 at 09:05:01PM -0800, Junio C Hamano wrote:
> You are much better off to keep /usr/src/rootstuff/.git (and > working tree files are /usr/src/rootstuff/etc/hosts and > friends), have a build procedure (read: Makefile) there, and > version control that source directory. I usually have 'install' > and 'diff' target in that Makefile, so that I can do this:
A while back I wrote CVSMan, which tries to be berkeley sup(8) with CVS as the transport. I think git would work well here, but I haven't yet generalized the code to support non-CVS SCMs (I certainly have wanted to, it's the only thing I use CVS for anymore). Like GIT, CVS doesn't do perms well. However, CVSMan handles the perms via .cvsperms files.
Joel
-- "What does it say about a society's priorities when the time you spend in meetings on Monday is greater than the total number of hours you spent sleeping over the weekend?" - Nat Friedman Joel Becker Principal Software Developer Oracle E-mail: joel.becker@oracle.com Phone: (650) 506-8127
Re: /etc in git?
On Wed, 18 Jan 2006, Junio C Hamano wrote:
> Adam Hunt <kinema@gmail.com> writes: > > > Do you have any more details by chance? Does it work? Does it work > > well? How does one do it? > > I personally feel it is a horrible and stupid thing to do, if by > "version control /etc" you mean to have /.git which controls > /etc/hosts and stuff in place. It would work (git does not > refuse to run as root). But being a *source* control system, we > deliberately refuse to store the full permission bits, so if > your /etc/shadow is mode 0600 while /etc/hosts is mode 0644, you > have to make sure they stay that way after checking things out.
At some point, people considered setting up an object type that would have all of the bits. That is, if you want a directory to come out literally the same as it went in, uid/gid/sticky-bit and all, you'd do something special to make this happen.
I think you could do some nifty stuff where you have git take care of /etc, and make all your changes to clones of the repository, push them, and check them out. I bet you could even have three-way merge on package installs this way; install the package into a fake root that has the /etc generated by the install of the previous version of the package (i.e., without your changes), commit that head, then merge that head into your master branch etc (in a non-real working tree, of course), check over the result, commit, push to the real repository, and check out. For that matter, you could probably generate the "package added replacing previous package" commit without using a working tree, directly from the package.
(Sure, it's currently set up for source control only, but the original theory was general content, and it should be good at producing exactly the right directory structure if it had a type to represent exact stuff like that)
-Daniel *This .sig left intentionally blank*