Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve patch file validation to better detect missing file (v1) #585

Open
5 tasks done
damienmckenna opened this issue Jul 14, 2024 · 1 comment
Open
5 tasks done
Labels
bug Inconsistencies or issues which will cause a problem for users or implementors.

Comments

@damienmckenna
Copy link

Verification

  • I have updated Composer to the most recent stable release (composer self-update)
  • I have updated Composer Patches to the most recent stable release (composer update cweagans/composer-patches)
  • I am using one of the supported PHP versions (8.0+)
  • I have searched existing issues and discussions for my problem.
  • My problem is not addressed in the troubleshooting guide.

What were you trying to do (and why)?

Applying a local patch file.

What happened? What did you expect to happen?

In Patches:: getAndApplyPatch() it uses the following logic:

// Local patch file.
if (file_exists($patch_url)) {
  $filename = realpath($patch_url);
}
else {
  // Generate random (but not cryptographically so) filename.
  $filename = uniqid(sys_get_temp_dir().'/') . ".patch";

  // Download file from remote filesystem to this location.
  $hostname = parse_url($patch_url, PHP_URL_HOST);

  try {
    $downloader->copy($hostname, $patch_url, $filename, false);
  } catch (\Exception $e) {
    // In case of an exception, retry once as the download might
    // have failed due to intermittent network issues.
    $downloader->copy($hostname, $patch_url, $filename, false);
  }
}

If the patch filename string is found as a file then it loads the file, otherwise it assumes the string is a valid URL and attempts to turn parse it as a URL so that it can then download the expected file.

There are several scenarios where this can fail:

  • The patch file doesn't exist locally because it wasn't added to the repository.
  • The patch file doesn't exist locally because of case sensitivity differences between when it was originally added and the "composer install" command was executed, e.g. "Filename.patch" vs "filename.patch" vs "filename.PATCH".
  • The patch filename was provided as an absolute path in the composer.json file and the absolute path is different on other environments, e.g. the patch was entered as "/Users/myaccount/Sites/mysite/patches/htaccess.patch" instead of just "patches/htaccess.patch".
  • The user account running the command does not have read access to the file.

Contents of composer.json

"drupal/core": {
                "Local changes to .htaccess.": "patches/htaccess.patch"
            },

Contents of patches.lock.json

n/a

Full output of composer patches-doctor

n/a

Full output of relevant Composer command with the -vvv flag added

n/a
@damienmckenna damienmckenna added the bug Inconsistencies or issues which will cause a problem for users or implementors. label Jul 14, 2024
@damienmckenna
Copy link
Author

damienmckenna commented Jul 14, 2024

A suggested solution would be to first look for a URL schema, if one isn't provided then assume it is a local path, e.g.:

// Local patch files don't include a URL schema, denoted by the "://"
// separator.
if (!strpos($patch_url, '://')) {
  if (file_exists($patch_url)) {
    $filename = realpath($patch_url);

    // Make sure the file is accessible.
    if (!is_readable($filename)) {
      throw new \Exception("Cannot access the local patch file $patch_url");
    }
  }
  else {
    throw new \Exception("Cannot find the local patch file $patch_url");
  }
}

// The requested patch is on a remote server.
else {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Inconsistencies or issues which will cause a problem for users or implementors.
Projects
None yet
Development

No branches or pull requests

1 participant