Repository: mesonbuild/meson

Issue:
gnome yelp: install fails with symlink_media if icon exists already
Running `ninja install` twice will error out with gnome.yelp():
```nstalling /tmp/nettool/help/ca/network-connectivity.page to /tmp/prefix/share/help/ca/gnome-nettool/network-connectivity.page
Symlinking /tmp/prefix/share/help/ca/gnome-nettool/figures/gnome-nettool-trail.png to /tmp/prefix/share/help/C/gnome-nettool/figures/gnome-nettool-trail.png.
Traceback (most recent call last):
  File "/home/tpm/Devel/meson/meson.py", line 37, in <module>
    sys.exit(main())
  File "/home/tpm/Devel/meson/meson.py", line 34, in main
    return mesonmain.run(launcher, sys.argv[1:])
  File "/home/tpm/Devel/meson/mesonbuild/mesonmain.py", line 269, in run
    sys.exit(run_script_command(args[1:]))
  File "/home/tpm/Devel/meson/mesonbuild/mesonmain.py", line 257, in run_script_command
    return cmdfunc(cmdargs)
  File "/home/tpm/Devel/meson/mesonbuild/scripts/yelphelper.py", line 114, in run
    destdir, options.project_id, options.symlinks)
  File "/home/tpm/Devel/meson/mesonbuild/scripts/yelphelper.py", line 82, in install_help
    os.symlink(srcfile, outfile)
FileExistsError: [Errno 17] File exists: '/tmp/prefix/share/help/C/gnome-nettool/figures/gnome-nettool-trail.png' -> '/tmp/prefix/share/help/ca/gnome-nettool/figures/gnome-nettool-trail.png'
Failed to run install script '/usr/bin/python3 /home/tpm/Devel/meson/meson.py --internal yelphelper install --subdir=help --id=gnome-nettool --installdir=share/help --sources=index.page@@introduction.page@@ip-information.page@@network-connectivity.page --symlinks=true --media=figures/gnome-nettool-trail.png@@figures/gnome-nettool.png --langs=ca@@cs@@da@@de@@el@@en_GB@@es@@fr@@hu@@ko@@oc@@pa@@pl@@pt_BR@@ru@@sv@@uk@@vi@@zh_CN'
FAILED: install 
```


Discussion:

Resolving patch:
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -598,7 +598,7 @@ def yelp(self, state, args, kwargs):
 
         langs = mesonlib.stringlistify(kwargs.pop('languages', []))
         media = mesonlib.stringlistify(kwargs.pop('media', []))
-        symlinks = kwargs.pop('symlink_media', False)
+        symlinks = kwargs.pop('symlink_media', True)
 
         if not isinstance(symlinks, bool):
             raise MesonException('symlink_media must be a boolean')
diff --git a/mesonbuild/scripts/yelphelper.py b/mesonbuild/scripts/yelphelper.py
--- a/mesonbuild/scripts/yelphelper.py
+++ b/mesonbuild/scripts/yelphelper.py
@@ -74,13 +74,24 @@ def install_help(srcdir, blddir, sources, media, langs, install_dir, destdir, pr
             if not os.path.exists(infile):
                 if lang == 'C':
                     mlog.warning('Media file "%s" did not exist in C directory' % m)
+                    continue
                 elif symlinks:
                     srcfile = os.path.join(c_install_dir, m)
                     mlog.log('Symlinking %s to %s.' % (outfile, srcfile))
                     if '/' in m or '\\' in m:
                         os.makedirs(os.path.dirname(outfile), exist_ok=True)
-                    os.symlink(srcfile, outfile)
-                continue
+                    try:
+                        try:
+                            os.symlink(srcfile, outfile)
+                        except FileExistsError:
+                            os.remove(outfile)
+                            os.symlink(srcfile, outfile)
+                        continue
+                    except (NotImplementedError, OSError):
+                        mlog.warning('Symlinking not supported, falling back to copying')
+                else:
+                    # Lang doesn't have media file so copy it over 'C' one
+                    infile = os.path.join(srcdir, 'C', m)
             mlog.log('Installing %s to %s' % (infile, outfile))
             if '/' in m or '\\' in m:
                 os.makedirs(os.path.dirname(outfile), exist_ok=True)


Test patch:
diff --git a/run_project_tests.py b/run_project_tests.py
--- a/run_project_tests.py
+++ b/run_project_tests.py
@@ -214,7 +214,8 @@ def validate_install(srcdir, installdir, compiler):
                 expected[platform_fix_name(line.strip())] = False
     # Check if expected files were found
     for fname in expected:
-        if os.path.exists(os.path.join(installdir, fname)):
+        file_path = os.path.join(installdir, fname)
+        if os.path.exists(file_path) or os.path.islink(file_path):
             expected[fname] = True
     for (fname, found) in expected.items():
         if not found:
diff --git a/test cases/frameworks/13 yelp/help/meson.build b/test cases/frameworks/13 yelp/help/meson.build
--- a/test cases/frameworks/13 yelp/help/meson.build	
+++ b/test cases/frameworks/13 yelp/help/meson.build	
@@ -3,5 +3,13 @@ gnome = import('gnome')
 gnome.yelp('meson',
    sources: 'index.page',
    media: 'media/test.txt',
+   symlink_media: false,
+   languages: ['de', 'es'],
+)
+
+gnome.yelp('meson-symlink',
+   sources: 'index.page',
+   media: 'media/test.txt',
+   symlink_media: true,
    languages: ['de', 'es'],
 )
diff --git a/test cases/frameworks/13 yelp/installed_files.txt b/test cases/frameworks/13 yelp/installed_files.txt
--- a/test cases/frameworks/13 yelp/installed_files.txt	
+++ b/test cases/frameworks/13 yelp/installed_files.txt	
@@ -3,3 +3,10 @@ usr/share/help/C/meson/media/test.txt
 usr/share/help/es/meson/index.page
 usr/share/help/es/meson/media/test.txt
 usr/share/help/de/meson/index.page
+usr/share/help/de/meson/media/test.txt
+usr/share/help/C/meson-symlink/index.page
+usr/share/help/C/meson-symlink/media/test.txt
+usr/share/help/es/meson-symlink/media/test.txt
+usr/share/help/es/meson-symlink/index.page
+usr/share/help/de/meson-symlink/index.page
+usr/share/help/de/meson-symlink/media/test.txt