{"id":20105082,"url":"https://github.com/jdee/pattern_patch","last_synced_at":"2026-03-01T20:34:53.827Z","repository":{"id":56887580,"uuid":"106753818","full_name":"jdee/pattern_patch","owner":"jdee","description":"pattern_patch gem","archived":false,"fork":false,"pushed_at":"2022-12-06T20:17:35.000Z","size":75,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-02-25T13:39:19.929Z","etag":null,"topics":["code-patching","erb","regexp"],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jdee.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-10-12T23:00:14.000Z","updated_at":"2023-02-08T08:58:20.000Z","dependencies_parsed_at":"2023-01-24T08:15:52.661Z","dependency_job_id":null,"html_url":"https://github.com/jdee/pattern_patch","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/jdee/pattern_patch","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdee%2Fpattern_patch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdee%2Fpattern_patch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdee%2Fpattern_patch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdee%2Fpattern_patch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jdee","download_url":"https://codeload.github.com/jdee/pattern_patch/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdee%2Fpattern_patch/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29954583,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-28T22:53:01.873Z","status":"ssl_error","status_checked_at":"2026-02-28T22:52:50.699Z","response_time":90,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["code-patching","erb","regexp"],"created_at":"2024-11-13T17:45:46.129Z","updated_at":"2026-03-01T20:34:53.792Z","avatar_url":"https://github.com/jdee.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pattern_patch gem\n\n[![Gem](https://img.shields.io/gem/v/pattern_patch.svg?style=flat)](https://rubygems.org/gems/pattern_patch)\n[![Downloads](https://img.shields.io/gem/dt/pattern_patch.svg?style=flat)](https://rubygems.org/gems/pattern_patch)\n[![License](https://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://github.com/jdee/pattern_patch/blob/master/LICENSE)\n[![CircleCI](https://img.shields.io/circleci/project/github/jdee/pattern_patch.svg)](https://circleci.com/gh/jdee/pattern_patch)\n\nApply and revert pattern-based patches to any string or text file.\n\nThis is a preliminary utility gem to apply and revert patches to strings (typically file contents). One\nof the main intended use cases for this plugin is source-code modification, e.g.\nwhen automatically integrating an SDK.\n\nPlease provide any feedback via issues in this repo.\n\nSee the [full documentation](http://www.rubydoc.info/github/jdee/pattern_patch/) for more details.\n\n```Ruby\nrequire \"pattern_patch\"\n\n# Add a meta-data key to the end of the application element of an Android manifest\nPatternPatch::Patch.new(\n  regexp: %r{^\\s*\u003c/application\u003e},\n  text: \"        \u003cmeta-data android:name=\\\"foo\\\" android:value=\\\"bar\\\" /\u003e\\n\",\n  mode: :prepend\n).apply \"AndroidManifest.xml\"\n```\n\nCapture groups may be used within the text argument in any mode. Note that\nthis works best without interpolation (single quotes or %q). If you use double\nquotes, the backslash must be escaped, e.g. `text: \"\\\\1\\\"MyOtherpod\\\"\"`.\n\n```Ruby\n# Change the name of a pod in a podspec\nPatternPatch::Patch.new(\n  regexp: /(s\\.name\\s*=\\s*)\"MyPod\"/,\n  text: '\\1\"MyOtherPod\"',\n  mode: :replace\n).apply \"MyPod.podspec\"\n```\n\nPatches in `:append` mode using capture groups in the text argument may be\nreverted. This is not currently supported in `:prepend` mode.\n\n#### Revert patches\n\nRevert patches by passing the optional `:revert` parameter:\n\n```Ruby\n# Revert the patch that added the metadata key to the end of the Android manifest, resulting in the original.\nPatternPatch::Patch.new(\n  regexp: %r{^\\s*\u003c/application\u003e},\n  text: \"        \u003cmeta-data android:name=\\\"foo\\\" android:value=\\\"bar\\\" /\u003e\\n\",\n  mode: :prepend\n).apply \"AndroidManifest.xml\"\n```\n\nPatches using the `:replace` mode cannot be reverted.\n\n#### Define patches in YAML files\n\nLoad a patch defined in YAML and apply it.\n\n```Ruby\nPatternPatch::Patch.from_yaml(\"patch.yaml\").apply \"file.txt\"\n```\n\n#### Define patch text in external files\n\nLoad the contents of a file to use for the insertion/substitution text:\n\n```Ruby\nPatternPatch::Patch.new(\n  regexp: /\\z/,\n  text_file: \"text_to_insert_at_end.txt\",\n  mode: :append\n)\n```\n\nWhen loading from a YAML file, the `text_file` path is interpreted relative\nto the directory of the YAML file, e.g.:\n\n**patch.yaml:**\n\n```YAML\ntext_file: text_to_insert_at_end.txt\n```\n\n```Ruby\nPatternPatch::Patch.from_yaml(\"/path/to/patches/patch.yaml\")\n```\n\nThis will load the contents of `/path/to/patches/text_to_insert_at_end.txt`.\n\n#### ERB in text and text_file\n\nERB is processed in the `text` value or the contents of a `text_file`:\n\n```Ruby\nPatternPatch::Patch.new(\n  regexp: /x/,\n  text: '\u003c%= PatternPatch::VERSION %\u003e',\n  mode: :replace\n).apply file_path\n```\n\nOptionally pass a `:binding` option to `#apply` to use a specific Binding:\n\n```Ruby\nreplacement_text = 'y'\nPatternPatch::Patch.new(\n  regexp: /x/,\n  text: '\u003c%= replacement_text %\u003e',\n  mode: :replace\n).apply file_path, binding: binding\n```\n\nor a Hash of locals for the template:\n```Ruby\nPatternPatch::Patch.new(\n  regexp: /x/,\n  text: '\u003c%= replacement_text %\u003e',\n  mode: :replace\n).apply file_path, locals: { replacement_text: 'y' }\n```\n\nThis is particularly useful with a `text_file` argument.\n\nThe `#apply` and `#revert` methods also accept `:safe_level` and `:trim_mode`\noptions for use with ERb. These can be set at the global level using\n`PatternPatch.safe_level` and `PatternPatch.trim_mode`. The `#safe_level`\nand '#trim_mode' attributes in the `Methods` module are convenience methods\nto set and retrieve these global values.\n\n```Ruby\nPatternPatch::Patch.new(\n  regexp: /x/,\n  text_file: \"template.erb\",\n  mode: :replace\n).apply file_path, trim_mode: \"\u003c\u003e\"\n```\n\n#### Regular expressions with modifiers in YAML\n\nThe `regexp` field in a YAML file may be specified with or without slashes\nor a modifier:\n\n```YAML\n# Results in /^x/\nregexp: '^x'\n```\n\n```YAML\n# Results in /^x/i\nregexp: '/^x/i'\n```\n\nCurrently only the slash literal notation is supported in YAML.\n\n#### Loading patches from a specific folder\n\nUse `PatternPatch.patch_dir` and `PatternPatch.patch` to easily load patches\nby name.\n\n```Ruby\nPatternPatch.patch_dir = \"/path/to/patches\"\n# Use /path/to/patches/patch_name.yml\nPatternPatch.patch(:patch_name).apply file_path\n```\n\n#### Configuration with patch_config method\n\n```Ruby\ninclude PatternPatch::Methods\n\npatch_config do |c|\n  c.patch_dir = File.expand_path '../assets/patches', __dir__\n  c.trim_mode = '\u003c\u003e'\nend\n\npatch(:my_patch).apply '/path/to/target/file'\n```\n\nor\n\n```Ruby\ninclude PatternPatch::Methods\n\npatch_config.patch_dir = File.expand_path '../assets/patches', __dir__\npatch_config.trim_mode = '\u003c\u003e'\n\npatch(:my_patch).apply '/path/to/target/file'\n```\n\n### Why use pattern_patch?\n\nModifying files from code is a common task. When modifying a file that uses a\nstandard format, such as XML or JSON, you can use a standard library in almost\nany language to parse, interpret and update file contents.\n\nIf you have to patch other formatted text, particularly source code, there may\nnot be a standard library available to parse a given format. In addition, using\na library limits control over formatting. If you use REXML to modify XML, it\nwill generate a file using single quotes for all attributes. While this is\nlegitimate XML, it can cause problems in some cases, and it generates a diff\nthat shows irrelevant, inconsequential changes. Some XML libraries\ncan make other changes to the file format, such as joining multiline tags. In\nsome cases (e.g., Android manifests) this is quite visible and annoying.\n\nThis gem offers a more general solution to the problem. A `Patch` is defined as\nan operation that can be performed on any file at all. If the file's contents do\nnot match the `#regexp` attribute, no change is made, but the patch may still be\napplied. These operations may be\nexternally defined in separate files or in code (or using a combination of\nboth). Further, many patches may be reverted by recognizing\nthe pattern that would result from application of the patch and reversing its\neffect.\n\nThis gem is used extensively in the\n[branch_io_cli](https://github.com/BranchMetrics/branch_io_cli) gem to patch\nsource code, Podfiles and Cartfiles. A collection of patches is kept in\n`lib/assets/patches`, both YAML patch definitions and source patches using ERB.\nThe PatchHelper class easily loads the patch assets and applies them to the\nrelevant files. The process there is similar to rendering partial templates in a\nweb framework like Rails. It is also used in the\n[patch](https://github.com/jdee/fastlane-plugin-patch) plugin for Fastlane. In\nfact this gem grew out of that plugin.\n\nThis idea was loosely inspired by Facebook's\n[`react-native link` automation for Android](https://github.com/facebook/react-native/tree/master/local-cli/link/android/patches).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdee%2Fpattern_patch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjdee%2Fpattern_patch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdee%2Fpattern_patch/lists"}