Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 275237 - emerge silently skips config protected files if a directory has taken it's place
Summary: emerge silently skips config protected files if a directory has taken it's place
Status: RESOLVED FIXED
Alias: None
Product: Portage Development
Classification: Unclassified
Component: Core (show other bugs)
Hardware: All Linux
: High normal (vote)
Assignee: Portage team
URL:
Whiteboard:
Keywords: InVCS
Depends on:
Blocks: 288499
  Show dependency tree
 
Reported: 2009-06-24 00:11 UTC by Jonas Bernoulli
Modified: 2022-07-28 04:55 UTC (History)
0 users

See Also:
Package list:
Runtime testing required: ---


Attachments
patch to create ._cfg file (patch,1.07 KB, text/plain)
2009-06-24 00:13 UTC, Jonas Bernoulli
Details
mergeme() -> stat.S_ISREG() rewrite (vartree.py.diff,5.61 KB, patch)
2009-07-11 13:37 UTC, Jonas Bernoulli
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Jonas Bernoulli 2009-06-24 00:11:11 UTC
Studying vartree.py I have noticed that emerge behaves strangely when it finds that a config protected file has been replaced by a directory on the livesystem.

If the config protected file had just been edited emerge would instead merge a ._cfg file but if the file had instead been replaced with a directory it does not. This does not give the user a change merge the new default configuration with his local changes.

The attached patch fixes this by creating the ._cfg file. However etc-update fails to do something reasonable with it. But at least the user now sees that the file has changed.

Reproducible: Always

Steps to Reproduce:
1. Replace a config protected file with a directory
2. Install new version of the respective package.
3. Don't be informed about the change.

Actual Results:  
creates no ._0000_filename file

Expected Results:  
create a ._0000_filename file

This is how etc-update fails after the above patch has been applied:

$ tree -a /etc
/etc
|-- ._cfg0000_foo.conf
|-- foo.conf (directory)
`-- ...
$ etc-update 
Scanning Configuration files...
diff: /etc/foo.conf/._cfg0000_foo.conf: No such file or directory
Automerging trivial changes in: /etc/foo.conf
Exiting: Nothing left to do; exiting. :)
NOTE: 1 updates remaining
$ tree -a /etc
/etc
|--foo.conf
|  `-- ._cfg0000_foo.conf
`--...

Running etc-update again using "replace original with update" obviously has to results in /etc/foo.conf/foo.conf. However etc-update should be able to detect that it can't trivially merge a file and a directory and inform the user in such a situation. But that is a different bug - let's first get emerge to create the ._cfg file.
Comment 1 Jonas Bernoulli 2009-06-24 00:13:26 UTC
Created attachment 195614 [details]
patch to create ._cfg file
Comment 2 Zac Medico gentoo-dev 2009-06-24 03:18:21 UTC
Thanks, this is in svn r13679.
Comment 3 Jonas Bernoulli 2009-07-11 13:34:02 UTC
Most of mergeme() is quite messy.  But I focus on the 'regular file' part because that is where I want to hook up some of my own code. So have started to refactor that part of the function.

I do so to make it easier to actually understand what's going on. So then I noticed other things that seem a strange:

A directory is not overwritten with a file even when it is NOT config protected. With my above patch (which you have already applied) the user will  at least notice but it still seems wrong:

(update from foo-1 to foo-2)

foo-1:
/etc/foo-config/
/etc/foo-config/foo-config
/usr/share/foo/data/
/usr/share/foo/data/part1
/usr/share/foo/data/part2

foo-2:
/etc/foo-config
/usr/share/foo/data

Sure the directory 'foo-config' should be protected but shouldn't this on the other hand just replace the directory 'data' with the file 'data'?

So I would change:

if stat.S_ISDIR(mydmode):
    ...
elif stat.S_ISREG(mydmode)...:
    if protected:
        ...
else:
    overwrite unconditionally

to

if protected:
    if stat.S_ISDIR(mydmode):
        ...
    elif stat.S_ISREG(mydmode)...:
else:
    overwrite unconditionally

I have also attached a patch containing my rewrite of this portion of the code. It can NOT be applied as is, as I first have to make sure that I have not overlooked any hidden behaviour in the old version.

My version should behave the same except that:

1. Doesn't protect all directories.  See above.

2. No error message is shown when the destination is blocked by a directory.

This error message is redundant because it now (see [1]) only affects config protected files) and the user will be informed about the conflicts anyway. Besides this isn't an error, just a special situation.

3. First check if 'mymd5 == md5-of-destination' then if 'mymd5 == saved-md5' not other way around.

The only difference this should make is that in very few cases destination is not overwritten by an IDENTICAL file as it would have with the current implementation.  So the user sees '---' instead of '>>>' but the end result on the livefs is the same.

My version has two 'if condition: pass' but that's a small price when replacing a maximum nesting of 6 with on of 2.

Some more problems are mentioned in the comments starting with '???'.

Comment 4 Jonas Bernoulli 2009-07-11 13:37:54 UTC
Created attachment 197547 [details, diff]
mergeme() -> stat.S_ISREG() rewrite
Comment 5 Zac Medico gentoo-dev 2010-09-22 04:08:36 UTC
(In reply to comment #2)
> Thanks, this is in svn r13679.

Via gitweb:

http://git.overlays.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=abf3368c778c9e615e5fa8acffcb2aa56fdd6a80

This was released in 2.1.7. Please file a new bug for any remaining issues.

(In reply to comment #4)
> Created an attachment (id=197547) [details]
> mergeme() -> stat.S_ISREG() rewrite

IIRC I didn't commit this patch because I found a bug in it. If you want, please rebase it against latest git and file a new bug.