Originally '*' has been used in the organize plugin which lead to an error due to the fact that the directory structure used by both parts (libvirt and qemu) is similar:
"path ./ already exists"
This error is cryptic unless you look at the source code of snapcraft:
def _organize_filesets(fileset, base_dir):
for key in sorted(fileset, key=lambda x: ['*' in x, x]):
src = os.path.join(base_dir, key)
dst = os.path.join(base_dir, fileset[key])
sources = iglob(src, recursive=True)
for src in sources:
if os.path.isdir(src) and '*' not in key: # <---- first file_utils.link_or_copy_tree(src, dst)
# TODO create alternate organization location to avoid
# deletions. shutil.rmtree(src)
elif os.path.isfile(dst): # <----- second raise EnvironmentError( 'Trying to organize file {key!r} to {dst!r}, ' 'but {dst!r} already exists'.format( key=key, dst=os.path.relpath(dst, base_dir)))
else: # <----- third os.makedirs(os.path.dirname(dst), exist_ok=True) shutil.move(src, dst)
The third code path is what gets picked in case there is a '*' in the key and the destination in not a file.
shutil.move is the call that gave 'path ./ already exists' error which I learned by grepping cpython source code:
def link_or_copy_tree(source_tree, destination_tree, copy_function=link_or_copy):
"""Copy a source tree into a destination, hard-linking if possile.
:param str source_tree: Source directory to be copied.
:param str destination_tree: Destination directory. If this directory # <<<<< already exists, the files in `source_tree` # <<<<< will take precedence. # <<<<<
The destination_tree argument gives a very good description in terms of what is going to happen but it is "hidden" in the source code which forces a regular snapcrafter to do some grepping.
Avoiding '*' helped me to select the right code path but it would be nice to have more visibility for that (either in a form of a knob in snapcraft.yaml or in the docs).
Hi,
I was working on a change for snap-libvirt and encountered a behavior which is not apparent on the first sight.
https:/ /github. com/openstack- snaps/snap- libvirt/ commit/ 8cd9af031a9b01f 360975bddc1964e 9380b983e6
Originally '*' has been used in the organize plugin which lead to an error due to the fact that the directory structure used by both parts (libvirt and qemu) is similar:
"path ./ already exists"
This error is cryptic unless you look at the source code of snapcraft:
def _organize: /github. com/snapcore/ snapcraft/ blob/9e00ffc151 b46026b414c8b4b 8e44a3a9d4c0b75 /snapcraft/ internal/ pluginhandler/ __init_ _.py#L449
https:/
calls def _organize_ filesets( fileset, base_dir): /github. com/snapcore/ snapcraft/ blob/9e00ffc151 b46026b414c8b4b 8e44a3a9d4c0b75 /snapcraft/ internal/ pluginhandler/ __init_ _.py#L907
https:/
Now this function has 3 code paths:
def _organize_ filesets( fileset, base_dir): join(base_ dir, key) join(base_ dir, fileset[key])
for key in sorted(fileset, key=lambda x: ['*' in x, x]):
src = os.path.
dst = os.path.
sources = iglob(src, recursive=True)
for src in sources:
file_ utils.link_ or_copy_ tree(src, dst)
shutil. rmtree( src) isfile( dst): # <----- second
raise EnvironmentError(
' Trying to organize file {key!r} to {dst!r}, '
' but {dst!r} already exists'.format(
key= key, dst=os. path.relpath( dst, base_dir)))
os.makedirs( os.path. dirname( dst), exist_ok=True)
shutil. move(src, dst)
if os.path.isdir(src) and '*' not in key: # <---- first
# TODO create alternate organization location to avoid
# deletions.
elif os.path.
else: # <----- third
The third code path is what gets picked in case there is a '*' in the key and the destination in not a file.
shutil.move is the call that gave 'path ./ already exists' error which I learned by grepping cpython source code:
def move function /hg.python. org/cpython/ file/2. 7/Lib/shutil. py#l306
https:/
Now, looking at an alternative code path (the first one) which calls link_or_copy_tree I see:
https:/ /github. com/snapcore/ snapcraft/ blob/05ba34a324 c781f3e454d88f8 8267c5356771f9a /snapcraft/ file_utils. py#L93
def link_or_ copy_tree( source_ tree, destination_tree,
copy_function= link_or_ copy):
already exists, the files in `source_tree` # <<<<<
will take precedence. # <<<<<
"""Copy a source tree into a destination, hard-linking if possile.
:param str source_tree: Source directory to be copied.
:param str destination_tree: Destination directory. If this directory # <<<<<
The destination_tree argument gives a very good description in terms of what is going to happen but it is "hidden" in the source code which forces a regular snapcrafter to do some grepping.
Avoiding '*' helped me to select the right code path but it would be nice to have more visibility for that (either in a form of a knob in snapcraft.yaml or in the docs).
Thanks!