Commit graph

14659 commits

Author SHA1 Message Date
David Rodríguez
d90a930ede [rubygems/rubygems] Properly protect writing binstubs with a file lock
There's an issue when multiple processes try to write the same binstub.
The problem is that our file locking mechanism is incorrect because
files are truncated _before_ they are locked. So it can happen that:

* Process A truncates binstub FOO.
* Process B truncates binstub FOO.
* Process A writes binstub FOO for gem BAR from the beginning of file.
* Process B writes binstub FOO for gem BAZ from the beginning of file.

If binstub FOO for gem BAR is bigger than binstub FOO for gem BAZ, then
some bytes will be left around at the end of the binstub, making it
corrupt.

This was not a problem in our specs until the spec testing binstubs with
the same name coming from different gems changed from using gems named
"fake" and "rack" to using gems named "fake" and "myrack". Because of
the difference in gem name length, the generated binstub for gem
"myrack" is now longer, causing the above problem if binstub for gem
myrack is written first.

The solution is to make sure when using flock to always use modes that
DON'T truncate the file when opening it. So, we use `r+` if the file
exists previously (it requires the file to exist previously), otherwise
we use `a+`.

ce8bcba90f
2024-07-08 14:38:30 +09:00
David Rodríguez
da12d63431 [rubygems/rubygems] Scope rescuing Errno::ENOLCK to just File.open
2a9d347d29
2024-07-08 14:38:29 +09:00
David Rodríguez
7cf7e7e2c0 [rubygems/rubygems] Add missing blank line after method documentation
2df7560ade
2024-07-08 14:38:29 +09:00
David Rodríguez
6db1c53fce [rubygems/rubygems] Remove unnecessary FileUtils usage
All other `chmod` usages in the file use `File.chmod`, so keep it
consistent.

3dc0cf8703
2024-07-08 14:38:28 +09:00
Stan Lo
abaa1b913d [ruby/irb] Bump version to v1.14.0
(https://github.com/ruby/irb/pull/980)

6a9e129714
2024-07-06 17:55:00 +00:00
Stan Lo
32ba86c9be [ruby/irb] Return only commands when completing help command's
argument
(https://github.com/ruby/irb/pull/973)

The command only takes command names as arguments, so we should only
return command names as candidates.

This will help users find a command faster as completion will be
another useful hint too.

7b6557cc24
2024-07-05 17:51:17 +00:00
なつき
88a2a46e23 [rubygems/rubygems] Restrict generic arm to only match 32-bit arm
14c4c16e96
2024-07-05 09:02:52 +00:00
Stan Lo
7fe5f0a1d0 [ruby/irb] Introduce cd command
(https://github.com/ruby/irb/pull/971)

It's essentially a combination of pushws and popws commands that are
easier to use.

Help message:

```
Usage: cd ([target]|..)

IRB uses a stack of workspaces to keep track of context(s), with `pushws` and `popws` commands to manipulate the stack.
The `cd` command is an attempt to simplify the operation and will be subject to change.

When given:
- an object, cd will use that object as the new context by pushing it onto the workspace stack.
- "..", cd will leave the current context by popping the top workspace off the stack.
- no arguments, cd will move to the top workspace on the stack by popping off all workspaces.

Examples:

  cd Foo
  cd Foo.new
  cd @ivar
  cd ..
  cd
```

4a0e0e89b7
2024-07-03 17:17:42 +00:00
Nobuyoshi Nakada
9aa62bda46 [ruby/shellwords] [DOC] Beautify links and formats
53e6ef2e71
2024-07-03 10:15:26 +00:00
Nobuyoshi Nakada
777fcd18a7 [ruby/shellwords] Satisfy rdoc -C
fa50d40a33
2024-07-03 10:15:23 +00:00
Nobuyoshi Nakada
7a43147407 [ruby/shellwords] Exclude unnecessary files from the packages
08c87a964e
2024-07-03 10:15:22 +00:00
Jerome Dalbert
2830a6ae38 [rubygems/rubygems] Only allow valid values for --test, --ci, and --linter options
d4360c9032
2024-07-02 19:54:23 +00:00
David Rodríguez
cd57c1294d [rubygems/rubygems] Only remove current platform when added right before resolution
If it has been explicitly added by `bundle lock --add-platform`, we
don't want to remove it.

09cf921dd6
2024-07-02 19:53:54 +00:00
David Rodríguez
7fc04276ac [rubygems/rubygems] Refactor previous fix a bit
1c80c6072f
2024-07-02 19:53:53 +00:00
Jerome Dalbert
d5500e621c [rubygems/rubygems] Feature add_dependency more prominently
0236cb6191
2024-07-02 19:53:29 +00:00
Stan Lo
d7af8afe1b [ruby/rdoc] Group code object files into the same directory
(https://github.com/ruby/rdoc/pull/1114)

It's hard to distinguish code object classes by their file names alone.
And given that we have 18 such classes, it'd make the codebase a lot
easier to understand if we grouped them into a single directory.

Given that these classes are all autoloaded in `lib/rdoc.rb` instead
of required individually, this change should have minimum impact on
projects using RDoc as they generally just require `rdoc`, not individual
files. An example is Rails' `sdoc`:
https://github.com/rails/sdoc/blob/main/lib/sdoc/rdoc_monkey_patches.rb

4211292ffe
2024-07-02 10:15:00 +00:00
Yudai Takada
15ceb95d78 [ruby/rdoc] Fix some typos (https://github.com/ruby/rdoc/pull/1129)
* constist ==> consist

* Tidyness ==> Tidiness

* Currentry ==> Currently

* valus ==> values

8412705721
2024-07-01 11:08:37 +09:00
tomoya ishida
de2d9c8e22 [ruby/irb] Allow assigning and using local variable name conflicting
with command
(https://github.com/ruby/irb/pull/961)

00603d470f
2024-06-30 17:13:27 +00:00
David Rodríguez
98c923ff4b
Synchronize Bundler & RubyGems (#11071) 2024-06-28 10:12:29 -04:00
David Rodríguez
5c826ebea5 [rubygems/rubygems] Protect binstub access during creation with a flock
88e3f1d23c
2024-06-28 10:49:07 +00:00
David Rodríguez
091a6ea8c1 [rubygems/rubygems] Move flock logic to its own method
91274128a8
2024-06-28 10:49:06 +00:00
David Rodríguez
f41a2c96c3 [rubygems/rubygems] More compact open_file fallback on Windows
8f34396af6
2024-06-28 10:49:06 +00:00
David Rodríguez
815b345b41 [rubygems/rubygems] Print a proper error when bin dir does not have writable permission bit
979cd898f9
2024-06-27 12:53:05 +00:00
David Rodríguez
d29a76b90b [rubygems/rubygems] Only override pre_install_checks when necessary
RubyGems >= 3.5 no longer raises `Gem::FilePermissionError` explicitly.

df54b9fd90
2024-06-27 12:53:04 +00:00
Jerome Dalbert
c6c817df28 [rubygems/rubygems] Add --no-test, --no-ci, and --no-linter options
f58660ffcc
2024-06-26 11:24:47 +00:00
Thomas Marshall
b88ac94eec [rubygems/rubygems] Only validate resolution info in Bundler
This commit switches out the full gemspec validation for a partial one
which only performs resolution related checks. This will allow gem
authors to run `bundle` commands immediately after creating a new gem
with Bundler, rather than having to fix metadata validation issues in
the default gemspec.

d5aa9cae9d
2024-06-25 14:32:20 +00:00
Thomas Marshall
39951293b4 [rubygems/rubygems] Add Specification#validate_for_resolution
This method validates only what is required for resolution, skipping any
irrelevant metadata validation. This will be used by Bundler instead of
doing a full validation, allowing gem authors to use `bundle` commands
immediately in newly created gems without first having to fix invalid
metafata fields in the default gemspec.

da7704cfc0
2024-06-25 14:32:19 +00:00
Josef Šimánek
bfb4272d8a [rubygems/rubygems] Regenerate bundler docs for June 2024.
72103ca1e8
2024-06-25 12:55:56 +00:00
tomoya ishida
691d85d342 [ruby/reline] Rerender and enter raw mode again by SIGCONT
(https://github.com/ruby/reline/pull/727)

be45660c83
2024-06-25 00:55:07 +00:00
ccmywish
185a6c991e [rubygems/rubygems] Update contents of gem.bat on Windows
(https://github.com/rubygems/rubygems/pull/6483)

41d8cffd2e

Co-Authored-By: MSP-Greg <Greg.mpls@gmail.com>
2024-06-21 02:27:47 +00:00
nick evans
b558fc0e36 [ruby/securerandom] Update UUID documentation with RFC9562 links
RFC9562 was released almost two weeks ago, so we can replace the "draft"
UUIDv7 URL with the final RFC URL too.  RFC9562 obsoletes RFC4122, so I
replaced its link as well.

1e41c3d2cb
2024-06-20 08:34:31 +00:00
David Rodríguez
f7acfeb4ce [rubygems/rubygems] Fix credentials being readded when re-resolving without a full unlock
a8670e43f8
2024-06-20 07:15:06 +00:00
David Rodríguez
bf6b8dd6a8 [rubygems/rubygems] Fix bundle update <gem_name> edge case
When locked only to RUBY, and some locked spec does not meet locked
dependencies, Bundler would remove the only locked platform and end up
creating a lockfile with empty sections.

We can't rely on our criteria to remove invalid platforms if locked
specs are not valid in the first place.

1dba05cf53
2024-06-20 07:14:47 +00:00
David Rodríguez
ae7d609456 [rubygems/rubygems] Don't expire git specs unnecessarily when remote! or cached! are used
04b26731cb
2024-06-20 15:22:20 +09:00
David Rodríguez
0610302a8f [rubygems/rubygems] Don't validate local gemspec twice
Calling `remote!` or `cached!` on the source was expiring local specs
for now reason. It's unnecessary to override these methods for path
sources since they only deal with local specifications.

aa93b196a2
2024-06-20 15:22:13 +09:00
David Rodríguez
758e01d39d [rubygems/rubygems] Make sure to not re-resolve when a not fully specific local platform is locked
36a02c6128
2024-06-20 15:21:08 +09:00
David Rodríguez
c6a28b02c9 [rubygems/rubygems] Always resolve against the local platform
If RUBY is the only platform in the lockfile, we were skipping adding
the local platform to the list of resolution platforms. This generally
works anyways, because we had some code to still add it if the RUBY
platform is not valid for the set of locked gems.

However, sometimes it can happen that "RUBY" is valid for the current
set of locked gems, but when adding a new dependency, it becomes
invalid. For example, when adding sorbet to a Gemfile, that will
introduce `sorbet-static` as an indirect dependency which does not have
a generic "RUBY" variant. This will cause resolution to take a long time
continuously backtracking trying to find solutions that don't introduce
`sorbet-static` as a dependency and will eventually fail.

Instead, we can always add the local platform to the set of resolution
platforms before resolving, and remove it as necessary after resolution
so that we lock the correct set of platforms.

6ed1fe6050
2024-06-20 15:20:57 +09:00
David Rodríguez
9e713f0e8c [rubygems/rubygems] Remove no longer needed condition
The `force-ruby-platform` settings is properly respected when
materializing since e17d7e9efb.

c4ba54eb96
2024-06-20 15:20:47 +09:00
Martin Emde
af304ad952 [rubygems/rubygems] Revert to splitting parser due to performance regression
* The string search parser was more memory efficient but
  in some cases, much slower. Reverting until a better
  solution is found.
* Handle the situation where the line might be blank (Artifactory bug)

222d38737d
2024-06-20 15:18:56 +09:00
Yuri Kanivetsky
84c9f2a240 [rubygems/rubygems] Make "bundler? update --bundler" behave identically
30dce3f87d
2024-06-20 00:12:31 +00:00
Kevin Newton
24f48382bc [ruby/prism] (parser) Fix up tokens for empty symbol
5985ab7687
2024-06-18 21:18:39 -04:00
Earlopain
b8a592fe6e [rubygems/rubygems] Fix bundle fund when the gemfile contains optional groups
`current_dependencies` doesn't return gems in optional groups, while `specs` would

Closes https://github.com/rubygems/rubygems/pull/7757

c797e95636
2024-06-18 17:53:59 +00:00
Aaron Patterson
cdf33ed5f3 Optimized forwarding callers and callees
This patch optimizes forwarding callers and callees. It only optimizes methods that only take `...` as their parameter, and then pass `...` to other calls.

Calls it optimizes look like this:

```ruby
def bar(a) = a
def foo(...) = bar(...) # optimized
foo(123)
```

```ruby
def bar(a) = a
def foo(...) = bar(1, 2, ...) # optimized
foo(123)
```

```ruby
def bar(*a) = a

def foo(...)
  list = [1, 2]
  bar(*list, ...) # optimized
end
foo(123)
```

All variants of the above but using `super` are also optimized, including a bare super like this:

```ruby
def foo(...)
  super
end
```

This patch eliminates intermediate allocations made when calling methods that accept `...`.
We can observe allocation elimination like this:

```ruby
def m
  x = GC.stat(:total_allocated_objects)
  yield
  GC.stat(:total_allocated_objects) - x
end

def bar(a) = a
def foo(...) = bar(...)

def test
  m { foo(123) }
end

test
p test # allocates 1 object on master, but 0 objects with this patch
```

```ruby
def bar(a, b:) = a + b
def foo(...) = bar(...)

def test
  m { foo(1, b: 2) }
end

test
p test # allocates 2 objects on master, but 0 objects with this patch
```

How does it work?
-----------------

This patch works by using a dynamic stack size when passing forwarded parameters to callees.
The caller's info object (known as the "CI") contains the stack size of the
parameters, so we pass the CI object itself as a parameter to the callee.
When forwarding parameters, the forwarding ISeq uses the caller's CI to determine how much stack to copy, then copies the caller's stack before calling the callee.
The CI at the forwarded call site is adjusted using information from the caller's CI.

I think this description is kind of confusing, so let's walk through an example with code.

```ruby
def delegatee(a, b) = a + b

def delegator(...)
  delegatee(...)  # CI2 (FORWARDING)
end

def caller
  delegator(1, 2) # CI1 (argc: 2)
end
```

Before we call the delegator method, the stack looks like this:

```
Executing Line | Code                                  | Stack
---------------+---------------------------------------+--------
              1| def delegatee(a, b) = a + b           | self
              2|                                       | 1
              3| def delegator(...)                    | 2
              4|   #                                   |
              5|   delegatee(...)  # CI2 (FORWARDING)  |
              6| end                                   |
              7|                                       |
              8| def caller                            |
          ->  9|   delegator(1, 2) # CI1 (argc: 2)     |
             10| end                                   |
```

The ISeq for `delegator` is tagged as "forwardable", so when `caller` calls in
to `delegator`, it writes `CI1` on to the stack as a local variable for the
`delegator` method.  The `delegator` method has a special local called `...`
that holds the caller's CI object.

Here is the ISeq disasm fo `delegator`:

```
== disasm: #<ISeq:delegator@-e:1 (1,0)-(1,39)>
local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 1] "..."@0
0000 putself                                                          (   1)[LiCa]
0001 getlocal_WC_0                          "..."@0
0003 send                                   <calldata!mid:delegatee, argc:0, FCALL|FORWARDING>, nil
0006 leave                                  [Re]
```

The local called `...` will contain the caller's CI: CI1.

Here is the stack when we enter `delegator`:

```
Executing Line | Code                                  | Stack
---------------+---------------------------------------+--------
              1| def delegatee(a, b) = a + b           | self
              2|                                       | 1
              3| def delegator(...)                    | 2
           -> 4|   #                                   | CI1 (argc: 2)
              5|   delegatee(...)  # CI2 (FORWARDING)  | cref_or_me
              6| end                                   | specval
              7|                                       | type
              8| def caller                            |
              9|   delegator(1, 2) # CI1 (argc: 2)     |
             10| end                                   |
```

The CI at `delegatee` on line 5 is tagged as "FORWARDING", so it knows to
memcopy the caller's stack before calling `delegatee`.  In this case, it will
memcopy self, 1, and 2 to the stack before calling `delegatee`.  It knows how much
memory to copy from the caller because `CI1` contains stack size information
(argc: 2).

Before executing the `send` instruction, we push `...` on the stack.  The
`send` instruction pops `...`, and because it is tagged with `FORWARDING`, it
knows to memcopy (using the information in the CI it just popped):

```
== disasm: #<ISeq:delegator@-e:1 (1,0)-(1,39)>
local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 1] "..."@0
0000 putself                                                          (   1)[LiCa]
0001 getlocal_WC_0                          "..."@0
0003 send                                   <calldata!mid:delegatee, argc:0, FCALL|FORWARDING>, nil
0006 leave                                  [Re]
```

Instruction 001 puts the caller's CI on the stack.  `send` is tagged with
FORWARDING, so it reads the CI and _copies_ the callers stack to this stack:

```
Executing Line | Code                                  | Stack
---------------+---------------------------------------+--------
              1| def delegatee(a, b) = a + b           | self
              2|                                       | 1
              3| def delegator(...)                    | 2
              4|   #                                   | CI1 (argc: 2)
           -> 5|   delegatee(...)  # CI2 (FORWARDING)  | cref_or_me
              6| end                                   | specval
              7|                                       | type
              8| def caller                            | self
              9|   delegator(1, 2) # CI1 (argc: 2)     | 1
             10| end                                   | 2
```

The "FORWARDING" call site combines information from CI1 with CI2 in order
to support passing other values in addition to the `...` value, as well as
perfectly forward splat args, kwargs, etc.

Since we're able to copy the stack from `caller` in to `delegator`'s stack, we
can avoid allocating objects.

I want to do this to eliminate object allocations for delegate methods.
My long term goal is to implement `Class#new` in Ruby and it uses `...`.

I was able to implement `Class#new` in Ruby
[here](https://github.com/ruby/ruby/pull/9289).
If we adopt the technique in this patch, then we can optimize allocating
objects that take keyword parameters for `initialize`.

For example, this code will allocate 2 objects: one for `SomeObject`, and one
for the kwargs:

```ruby
SomeObject.new(foo: 1)
```

If we combine this technique, plus implement `Class#new` in Ruby, then we can
reduce allocations for this common operation.

Co-Authored-By: John Hawthorn <john@hawthorn.email>
Co-Authored-By: Alan Wu <XrXr@users.noreply.github.com>
2024-06-18 09:28:25 -07:00
Stan Lo
921f22e563 [ruby/irb] Improve how command calls' return value is handled
(https://github.com/ruby/irb/pull/972)

In #934, we changed command calls to return nil only. This PR improves
the behaviour even further by:

- Not echoing the `nil` returned by command calls
- Not overriding previous return value stored in `_` with the
  `nil` from commands

c844176842
2024-06-18 15:15:23 +00:00
tomoya ishida
c2e2c5975d [ruby/reline] Fix vi_yank or vi_delete_meta copies nil bug
(https://github.com/ruby/reline/pull/726)

46b30b07c9
2024-06-18 14:57:19 +00:00
Alexey Schepin
a3930db275 [rubygems/rubygems] Delete extra spaces left after rubocop autofix
a552732bed
2024-06-18 01:52:04 +00:00
Yuta Saito
d914192012 [rubygems/rubygems] Use symbol for option key in Bundler::CLI::Install
07a5faeb89
2024-06-18 00:59:37 +00:00
Yuta Saito
97a23db5ac [rubygems/rubygems] Disable install_extension_in_lib when cross-compiling
643e154f32
2024-06-18 00:59:36 +00:00
Yuta Saito
3e4b694565 [rubygems/rubygems] Bundler integration for --target-rbconfig option
f9fb413a19
2024-06-18 00:59:36 +00:00
Yuta Saito
273d41b9e3 [rubygems/rubygems] Add --target-rbconfig option to gem install and gem update commands
This patch adds `--target-rbconfig` option to specify the rbconfig.rb file
for the deployment target platform. This is useful when cross-compiling
gems. At the moment, this option is only available for `extconf.rb`-based
extensions.

cf2843f7a2
2024-06-18 00:59:35 +00:00