Re: Macros to modify gem dependencies

2016-09-16 Thread Vít Ondruch


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

2016-09-15 Thread Pavel Valena

- 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

2016-09-15 Thread Vít Ondruch


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

2016-09-15 Thread František Dvořák
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

2016-09-15 Thread Vít Ondruch
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

2016-09-15 Thread Vít Ondruch


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

2016-09-15 Thread Vít Ondruch
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