Re: Macros to modify gem dependencies
Dne 15.9.2016 v 20:12 Pavel Valena napsal(a): > - Original Message - >> From: "Vít Ondruch" <vondr...@redhat.com> >> To: ruby-sig@lists.fedoraproject.org >> Sent: Thursday, September 15, 2016 2:00:59 PM >> Subject: Re: Macros to modify gem dependencies >> >> >> >> Dne 15.9.2016 v 10:06 Vít Ondruch napsal(a): >>> BTW this is first draft of the macros. I am going to try second >>> implementation, which will probably need to use a bit different syntax >>> for macro calls, but it might replace the 3 lines usage example above >>> with 2 lines version: >>> >>> >>> ``` >>> >>> %gemspec_remove_runtime_dependency -n fog-dynect >>> %gemspec_add_runtime_dependency -n fog-dynect ['~> 10.0', '>= 10.1'] >>> >>> ``` > The above gives me strange result in gemspec > > ``` > s.add_runtime_dependency(%q, [">= 10.1", ">= 10.1", "~> 10.0"]) > > ``` Unless you fixed "gemspec_remove_runtime_dependency" by yourself, it does not support the -n parameter yet, hence the dependency is not cleaned up prior adding new dependencies. > > However, > > ``` > %gemspec_add_dep -n fog-dynect '~> 10.0' > > ``` > > results in > > ``` > s.add_dependency(%q, [">= 10.1", "~> 10.0"]) > > ``` > > Which I consider correct for the first example. > > > Also, using the notation below does not produce expected result > > ``` > %gemspec_remove_dep fog-dynect > %gemspec_add_dep -n fog-dynect '~> 10.0' > %gemspec_add_dep -n fog-dynect '>= 10.1' > > ``` > > => > > ``` > s.add_dependency(%q, ["~> 10.0"]) > > ``` > > FTR, in case of the non-named-variable-macro version (without '-n') the > result is correct. > > >>> >> As I promised, this is implementation with the '-n' parameter: >> >> ``` >> %define gemspec_add_runtime_dependency(n:) \ >> read -d '' add_runtime_dependency_script << 'EOR' || : \ >> name = '%{-n*}' \ >> version = %{*} \ >> spec = Gem::Specification.load('.%{gem_spec}') \ >> dep = spec.dependencies.detect { |d| d.type == :runtime && d.name == >> name } \ >> if dep \ >> dep.requirement.concat version \ >> else \ >> spec.add_runtime_dependency name, version \ >> end \ >> File.write '.%{gem_spec}', spec.to_ruby \ >> EOR\ >> echo "$add_runtime_dependency_script" | ruby \ >> %{nil} >> >> ``` > The above can be also written as > > ``` > %define gemspec_add_dep(n:) \ > echo ' \ > name = %q<%{-n*}> \ > version = %{*} \ > spec = Gem::Specification.load(%q<.%{gem_spec}>) \ > dep = spec.dependencies.detect { |d| d.type == :runtime && d.name == name } > \ > if dep \ > dep.requirement.concat version \ > else \ > spec.add_runtime_dependency name, version \ > end \ > File.write %q<.%{gem_spec}>, spec.to_ruby \ > ' | ruby > %{nil} > > ``` Yes, you can write it like this, but you have to be careful about the usage later, e.g. the example you have used above: ``` %gemspec_add_dep -n fog-dynect '~> 10.0' ``` is probably reason for the issues you have described. If checked the log output correctly, you would see following output: ``` + echo ' name = %q version = ~' /var/tmp/rpm-tmp.4CWGoP: line 71: 10.0 spec = Gem::Specification.load(%q<./usr/share/gems/specifications/fog-1.38.0.gemspec>) dep = spec.dependencies.detect { |d| d.type == :runtime && d.name == name } if dep dep.requirement.concat version else spec.add_runtime_dependency name, version end File.write %q<./usr/share/gems/specifications/fog-1.38.0.gemspec>, spec.to_ruby : No such file or directory + ruby ``` The correct usage for this would be: ``` %gemspec_add_dep -n fog-dynect "~> 10.0" ``` IOW please note the single vs double quotes ... Vít ___ ruby-sig mailing list ruby-sig@lists.fedoraproject.org https://lists.fedoraproject.org/admin/lists/ruby-sig@lists.fedoraproject.org
Re: Macros to modify gem dependencies
- Original Message - > From: "Vít Ondruch" <vondr...@redhat.com> > To: ruby-sig@lists.fedoraproject.org > Sent: Thursday, September 15, 2016 2:00:59 PM > Subject: Re: Macros to modify gem dependencies > > > > Dne 15.9.2016 v 10:06 Vít Ondruch napsal(a): > > BTW this is first draft of the macros. I am going to try second > > implementation, which will probably need to use a bit different syntax > > for macro calls, but it might replace the 3 lines usage example above > > with 2 lines version: > > > > > > ``` > > > > %gemspec_remove_runtime_dependency -n fog-dynect > > %gemspec_add_runtime_dependency -n fog-dynect ['~> 10.0', '>= 10.1'] > > > > ``` The above gives me strange result in gemspec ``` s.add_runtime_dependency(%q, [">= 10.1", ">= 10.1", "~> 10.0"]) ``` However, ``` %gemspec_add_dep -n fog-dynect '~> 10.0' ``` results in ``` s.add_dependency(%q, [">= 10.1", "~> 10.0"]) ``` Which I consider correct for the first example. Also, using the notation below does not produce expected result ``` %gemspec_remove_dep fog-dynect %gemspec_add_dep -n fog-dynect '~> 10.0' %gemspec_add_dep -n fog-dynect '>= 10.1' ``` => ``` s.add_dependency(%q, ["~> 10.0"]) ``` FTR, in case of the non-named-variable-macro version (without '-n') the result is correct. > > > > > > As I promised, this is implementation with the '-n' parameter: > > ``` > %define gemspec_add_runtime_dependency(n:) \ > read -d '' add_runtime_dependency_script << 'EOR' || : \ > name = '%{-n*}' \ > version = %{*} \ > spec = Gem::Specification.load('.%{gem_spec}') \ > dep = spec.dependencies.detect { |d| d.type == :runtime && d.name == > name } \ > if dep \ > dep.requirement.concat version \ > else \ > spec.add_runtime_dependency name, version \ > end \ > File.write '.%{gem_spec}', spec.to_ruby \ > EOR\ > echo "$add_runtime_dependency_script" | ruby \ > %{nil} > > ``` The above can be also written as ``` %define gemspec_add_dep(n:) \ echo ' \ name = %q<%{-n*}> \ version = %{*} \ spec = Gem::Specification.load(%q<.%{gem_spec}>) \ dep = spec.dependencies.detect { |d| d.type == :runtime && d.name == name } \ if dep \ dep.requirement.concat version \ else \ spec.add_runtime_dependency name, version \ end \ File.write %q<.%{gem_spec}>, spec.to_ruby \ ' | ruby %{nil} ``` I was not sure whether I could use double quotes instead of single ones ``` echo " \ ... " | ruby ``` therefore I have used the %q< ... > notation in the ruby code instead. > > It is a bit more flexible, since what is following behind the name of > the dependency is pasted directly into Ruby code, so either ```['~> > 10.0', '>= 10.1']``` or '~> 10.0' are viable options. IOW, it must be > valid ruby code, otherwise the script bails out with error. E.g. for > > ``` > %gemspec_add_runtime_dependency -n fog-dynect ~> 10.0 > ``` > > the following error is reported: > > ``` > + read -d '' add_runtime_dependency_script > + : > + echo 'name = '\''fog-dynect'\'' > version = ~> 10.0 > spec = > Gem::Specification.load('\''./usr/share/gems/specifications/fog-1.38.0.gemspec'\'') > > dep = spec.dependencies.detect { |d| d.type == :runtime && d.name == > name } > if dep > dep.requirement.concat version > else > spec.add_runtime_dependency name, version > end > File.write '\''./usr/share/gems/specifications/fog-1.38.0.gemspec'\'', > spec.to_ruby' > + ruby > -:2: syntax error, unexpected '>' > version = ~> 10.0 > ^ > ``` > > > Vít > ___ > ruby-sig mailing list > ruby-sig@lists.fedoraproject.org > https://lists.fedoraproject.org/admin/lists/ruby-sig@lists.fedoraproject.org > Pavel Valena Associate Software Engineer Brno, Czech Republic RED HAT | TRIED. TESTED. TRUSTED. All of the airlines in the Fortune Global 500 rely on Red Hat. Find out why at Trusted | Red Hat <http://www.redhat.com/en/about/trusted> ___ ruby-sig mailing list ruby-sig@lists.fedoraproject.org https://lists.fedoraproject.org/admin/lists/ruby-sig@lists.fedoraproject.org
Re: Macros to modify gem dependencies
Dne 15.9.2016 v 14:53 František Dvořák napsal(a): > Hi, > > for inspiration: maven packages are using these macros: > > %pom_add_dep > %pom_add_plugin > %pom_remove_dep > %pom_remove_plugin > > What about similar shorter names for gems?: > > %gemspec_add_dep > %gemspec_remove_dep > > Just an idea. There wouldn't be clear the macros are changing runtime > dependency... You are right, the shorter version might be better. Thinking about the runtime part, is it actually relevant information? Will we ever change development dependency? If yes, may be something like additional '-d' option would be better ... Thx for the feedback! Vít ___ ruby-sig mailing list ruby-sig@lists.fedoraproject.org https://lists.fedoraproject.org/admin/lists/ruby-sig@lists.fedoraproject.org
Re: Macros to modify gem dependencies
Hi, for inspiration: maven packages are using these macros: %pom_add_dep %pom_add_plugin %pom_remove_dep %pom_remove_plugin What about similar shorter names for gems?: %gemspec_add_dep %gemspec_remove_dep Just an idea. There wouldn't be clear the macros are changing runtime dependency... Frantisek Vít Ondruch píše v Čt 15. 09. 2016 v 10:06 +0200: > Hi, > > From time to time, it is necessary to modify the gem dependencies we > ship. For example, it is good idea to remove the Mac/Windows specific > dependencies from Listen gem or sometimes it is necessary to relax > some > gem dependency. Historically, we did that using sed or applying > patches. > I don't think neither is optimal solution. So lately, I was thinking > about introducing macros to achieve this. > > I am thinking about two macros ATM and here is their implementation: > > > ``` > > %global gemspec_add_runtime_dependency() \ > read -d '' add_runtime_dependency_script << 'EOR' || : \ > options = %w(%{*}) \ > name = options.shift \ > version = [options.join(' ')] \ > spec = Gem::Specification.load('.%{gem_spec}') \ > dep = spec.dependencies.detect { |d| d.type == :runtime && d.name > == > name } \ > if dep \ > dep.requirement.concat version \ > else \ > spec.add_runtime_dependency name, version \ > end \ > File.write '.%{gem_spec}', spec.to_ruby \ > EOR\ > echo "$add_runtime_dependency_script" | ruby\ > %{nil} > > %global gemspec_remove_runtime_dependency() \ > ruby \\\ > -e "name = '%{1}'" \\\ > -e "spec = Gem::Specification.load('.%{gem_spec}')" \\\ > -e "spec.dependencies.reject! { |d| d.type == :runtime && d.name == > name }" \\\ > -e "File.write '.%{gem_spec}', spec.to_ruby" \ > %{nil} > > ``` > > and you can use them as: > > > ``` > > %gemspec_remove_runtime_dependency fog-dynect > %gemspec_add_runtime_dependency fog-dynect ~> 10.0 > %gemspec_add_runtime_dependency fog-dynect >= 10.1 > > ``` > > As you can see, both are using a bit different way of implementation. > Let me discuss the details. > > > The 'gemspec_remove_runtime_dependency' is using bunch of '-e' > parameters to specify the code. The advantage of this approach is, > that > the build output log contains traces of the precise command which was > used, e.g.: > > > ``` > > + ruby -e 'name = '\''fog-dynect'\''' -e 'spec = > Gem::Specification.load('\''./usr/share/gems/specifications/fog- > 1.38.0.gemspec'\'')' > -e 'spec.dependencies.reject! { |d| d.type == :runtime && d.name == > name > }' -e 'File.write > '\''./usr/share/gems/specifications/fog-1.38.0.gemspec'\'', > spec.to_ruby' > > ``` > > > This is helpful, but the output is not very nice and the > implementation > is polluted with a lot of noise. > > The other approach used in 'gemspec_add_runtime_dependency' puts the > entire script into environment variable and then pipes it into the > ruby. > The log output looks like: > > > ``` > > + read -d '' add_runtime_dependency_script > + : > + echo 'options = %w(fog-dynect >= 10.1) > name = options.shift > version = [options.join('\'' '\'')] > spec = > Gem::Specification.load('\''./usr/share/gems/specifications/fog- > 1.38.0.gemspec'\'') > > dep = spec.dependencies.detect { |d| d.type == :runtime && d.name > == > name } > if dep > dep.requirement.concat version > else > spec.add_runtime_dependency name, version > end > File.write '\''./usr/share/gems/specifications/fog- > 1.38.0.gemspec'\'', > spec.to_ruby' > + ruby > > ``` > > Is this actually useful? Of course, the script could be piped > directly > into ruby without the env variable magic, but the output is then > reduced > just to: > > > ``` > > + ruby > > ``` > > which is not helpful at all (but could be improved by some hint as > "adding dependency "). > > So what is you opinion on usefulness of these macros and on the > implementation? What is the preferred way for you? > > > BTW this is first draft of the macros. I am going to try second > implementation, which will probably need to use a bit different > syntax > for macro calls, but it might replace the 3 lines usage example above > with 2 lines version: > > > ``` > > %gemspec_remove_runtime_dependency -n fog-dynect > %gemspec_add_runtime_dependency -n fog-dynect ['~> 10.0', '>= 10.1'] > > ``` > > Please share your thoughts on this topic. > > > Vít > > ___ > ruby-sig mailing list > ruby-sig@lists.fedoraproject.org > https://lists.fedoraproject.org/admin/lists/ruby-sig@lists.fedoraproj > ect.org ___ ruby-sig mailing list ruby-sig@lists.fedoraproject.org https://lists.fedoraproject.org/admin/lists/ruby-sig@lists.fedoraproject.org
Re: Macros to modify gem dependencies
Both approaches allows code injection, such as: ``` %gemspec_add_runtime_dependency -n fog-dynect ['~> 10.0', '>= 10.1.1']; puts requirements ``` But I don't consider this harmful Vít ___ ruby-sig mailing list ruby-sig@lists.fedoraproject.org https://lists.fedoraproject.org/admin/lists/ruby-sig@lists.fedoraproject.org
Re: Macros to modify gem dependencies
Dne 15.9.2016 v 10:06 Vít Ondruch napsal(a): > BTW this is first draft of the macros. I am going to try second > implementation, which will probably need to use a bit different syntax > for macro calls, but it might replace the 3 lines usage example above > with 2 lines version: > > > ``` > > %gemspec_remove_runtime_dependency -n fog-dynect > %gemspec_add_runtime_dependency -n fog-dynect ['~> 10.0', '>= 10.1'] > > ``` > > As I promised, this is implementation with the '-n' parameter: ``` %define gemspec_add_runtime_dependency(n:) \ read -d '' add_runtime_dependency_script << 'EOR' || : \ name = '%{-n*}' \ version = %{*} \ spec = Gem::Specification.load('.%{gem_spec}') \ dep = spec.dependencies.detect { |d| d.type == :runtime && d.name == name } \ if dep \ dep.requirement.concat version \ else \ spec.add_runtime_dependency name, version \ end \ File.write '.%{gem_spec}', spec.to_ruby \ EOR\ echo "$add_runtime_dependency_script" | ruby \ %{nil} ``` It is a bit more flexible, since what is following behind the name of the dependency is pasted directly into Ruby code, so either ```['~> 10.0', '>= 10.1']``` or '~> 10.0' are viable options. IOW, it must be valid ruby code, otherwise the script bails out with error. E.g. for ``` %gemspec_add_runtime_dependency -n fog-dynect ~> 10.0 ``` the following error is reported: ``` + read -d '' add_runtime_dependency_script + : + echo 'name = '\''fog-dynect'\'' version = ~> 10.0 spec = Gem::Specification.load('\''./usr/share/gems/specifications/fog-1.38.0.gemspec'\'') dep = spec.dependencies.detect { |d| d.type == :runtime && d.name == name } if dep dep.requirement.concat version else spec.add_runtime_dependency name, version end File.write '\''./usr/share/gems/specifications/fog-1.38.0.gemspec'\'', spec.to_ruby' + ruby -:2: syntax error, unexpected '>' version = ~> 10.0 ^ ``` Vít ___ ruby-sig mailing list ruby-sig@lists.fedoraproject.org https://lists.fedoraproject.org/admin/lists/ruby-sig@lists.fedoraproject.org
Macros to modify gem dependencies
Hi, From time to time, it is necessary to modify the gem dependencies we ship. For example, it is good idea to remove the Mac/Windows specific dependencies from Listen gem or sometimes it is necessary to relax some gem dependency. Historically, we did that using sed or applying patches. I don't think neither is optimal solution. So lately, I was thinking about introducing macros to achieve this. I am thinking about two macros ATM and here is their implementation: ``` %global gemspec_add_runtime_dependency() \ read -d '' add_runtime_dependency_script << 'EOR' || : \ options = %w(%{*}) \ name = options.shift \ version = [options.join(' ')] \ spec = Gem::Specification.load('.%{gem_spec}') \ dep = spec.dependencies.detect { |d| d.type == :runtime && d.name == name } \ if dep \ dep.requirement.concat version \ else \ spec.add_runtime_dependency name, version \ end \ File.write '.%{gem_spec}', spec.to_ruby \ EOR\ echo "$add_runtime_dependency_script" | ruby\ %{nil} %global gemspec_remove_runtime_dependency() \ ruby \\\ -e "name = '%{1}'" \\\ -e "spec = Gem::Specification.load('.%{gem_spec}')" \\\ -e "spec.dependencies.reject! { |d| d.type == :runtime && d.name == name }" \\\ -e "File.write '.%{gem_spec}', spec.to_ruby" \ %{nil} ``` and you can use them as: ``` %gemspec_remove_runtime_dependency fog-dynect %gemspec_add_runtime_dependency fog-dynect ~> 10.0 %gemspec_add_runtime_dependency fog-dynect >= 10.1 ``` As you can see, both are using a bit different way of implementation. Let me discuss the details. The 'gemspec_remove_runtime_dependency' is using bunch of '-e' parameters to specify the code. The advantage of this approach is, that the build output log contains traces of the precise command which was used, e.g.: ``` + ruby -e 'name = '\''fog-dynect'\''' -e 'spec = Gem::Specification.load('\''./usr/share/gems/specifications/fog-1.38.0.gemspec'\'')' -e 'spec.dependencies.reject! { |d| d.type == :runtime && d.name == name }' -e 'File.write '\''./usr/share/gems/specifications/fog-1.38.0.gemspec'\'', spec.to_ruby' ``` This is helpful, but the output is not very nice and the implementation is polluted with a lot of noise. The other approach used in 'gemspec_add_runtime_dependency' puts the entire script into environment variable and then pipes it into the ruby. The log output looks like: ``` + read -d '' add_runtime_dependency_script + : + echo 'options = %w(fog-dynect >= 10.1) name = options.shift version = [options.join('\'' '\'')] spec = Gem::Specification.load('\''./usr/share/gems/specifications/fog-1.38.0.gemspec'\'') dep = spec.dependencies.detect { |d| d.type == :runtime && d.name == name } if dep dep.requirement.concat version else spec.add_runtime_dependency name, version end File.write '\''./usr/share/gems/specifications/fog-1.38.0.gemspec'\'', spec.to_ruby' + ruby ``` Is this actually useful? Of course, the script could be piped directly into ruby without the env variable magic, but the output is then reduced just to: ``` + ruby ``` which is not helpful at all (but could be improved by some hint as "adding dependency "). So what is you opinion on usefulness of these macros and on the implementation? What is the preferred way for you? BTW this is first draft of the macros. I am going to try second implementation, which will probably need to use a bit different syntax for macro calls, but it might replace the 3 lines usage example above with 2 lines version: ``` %gemspec_remove_runtime_dependency -n fog-dynect %gemspec_add_runtime_dependency -n fog-dynect ['~> 10.0', '>= 10.1'] ``` Please share your thoughts on this topic. Vít ___ ruby-sig mailing list ruby-sig@lists.fedoraproject.org https://lists.fedoraproject.org/admin/lists/ruby-sig@lists.fedoraproject.org