├── .gitignore ├── .ruby-version ├── Gemfile ├── README.md ├── examples ├── builder.yaml └── habitat.yaml ├── forkman-patch-git ├── forkman.rb └── habitat └── plan.sh /.gitignore: -------------------------------------------------------------------------------- 1 | .bundle/ 2 | Gemfile.lock 3 | results/ 4 | .secrets/ 5 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 3.4.0 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'mixlib-cli' 4 | gem 'ruby-filemagic' 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ForkMan 2 | 3 | This script helps you to refactor whole repositories by replacing all tokens using a user defined dictionary. 4 | 5 | ## ORDER 6 | 7 | **Dictionary order is important!** 8 | 9 | ## How it works 10 | 11 | It uses the provided dictionary and replaces each occurance of `term` with unique `token` with each file name and file content. Then it replaces `token` with new `term`. 12 | 13 | This helps to modify or keep unmodified content from the most unique `term` (better match) to general pattern. 14 | 15 | ## Why not just sed? 16 | 17 | consider the following example: 18 | 19 | ``` text 20 | I want to preserve original site: www.habitat.sh 21 | But replace this habitat with new name 22 | And use new hab binary 23 | ``` 24 | 25 | And we have the following naive dictionary: 26 | 27 | ``` text 28 | www.habitat.sh -> www.habitat.sh (I want to preserve this) 29 | habitat -> biome 30 | hab -> bio 31 | ``` 32 | 33 | You'll get wrong site: 34 | 35 | ``` text 36 | I want to preserve original site: www.biome.sh 37 | But replace this biome with new name 38 | And use new bio binary 39 | ``` 40 | 41 | # Usage Example 42 | 43 | The script [forkman-patch-git](forkman-patch-git) shows how it is possible to make a "hard-update" of new changes. 44 | 45 | It reverts local changes, so you should be careful. It takes `FORKMAN-UPSTREAM-BRANCH` branch and applies `forkman`. Then it resets to `FORKMAN_MAIN_BRANCH`, adds everything and commits. 46 | 47 | This emulates "manual project refactoring". If you satisfied with result you can merge this to your branch (or master). 48 | 49 | # Full example 50 | 51 | First ensure that you have forked the repository you want to operate on. (Eg: Fork habitat-sh/habitat to biome-sh/biome) 52 | 53 | Clone a repository: 54 | 55 | ``` 56 | git clone https://github.com/biome-sh/biome.git 57 | ``` 58 | 59 | Add an upstream repository: 60 | 61 | ``` 62 | cd biome 63 | git remote add habitat https://github.com/habitat-sh/habitat.git 64 | git remote update 65 | ``` 66 | 67 | Create translate dictionary `.forkman.yaml`. If you create file directly in repository, make sure you commit changes, because `forkman-patch-git` reverts all local changes. For experiments, you can keep config somewhere outside for a while: 68 | 69 | ``` 70 | cat < .forkman.yaml 71 | --- 72 | 73 | patterns: 74 | pattern1: replacement1 75 | pattern2: replacement2 76 | pattern3: replacement3 77 | 78 | deletes: 79 | - any 80 | - files 81 | - you 82 | - want 83 | - to 84 | - delete 85 | 86 | excludes: 87 | - files 88 | - you 89 | - dont 90 | - want 91 | - to 92 | - patch 93 | 94 | EOF 95 | ``` 96 | 97 | Create a `forkman-raw` branch: 98 | 99 | ``` 100 | git branch forkman-raw habitat/master 101 | git push origin forkman-raw 102 | ``` 103 | 104 | Install `forkman` using native way: 105 | 106 | ``` 107 | # install ruby 108 | gem install bundler 109 | bundle install 110 | ``` 111 | 112 | or via `habitat`/`biome`: 113 | 114 | ``` 115 | # Habitat 116 | sudo hab pkg install -fb jsirex/forkman 117 | 118 | # Biome 119 | sudo bio pkg install -fb jsirex/forkman 120 | ``` 121 | 122 | Run patches: 123 | 124 | ``` 125 | forkman-patch-git -u habitat/master 126 | ``` 127 | 128 | # Tip 129 | 130 | First patch on existing project will be huge and requires lots of your attention, but if you're using `forkman-patch-git` any further run will show only diffs related to a new code or dictionary changes. 131 | -------------------------------------------------------------------------------- /examples/builder.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # This is copy of habitat.yaml but with a few difference I need, like deleting Cargo.toml 4 | 5 | # Most uniq patterns should go first 6 | # !!! ORDER IS IMPORTANT !!! 7 | patterns: 8 | 9 | # Keep Original Sites 10 | www.habitat.sh: www.habitat.sh 11 | bldr.habitat.sh: bldr.habitat.sh 12 | forums.habitat.sh: forums.habitat.sh 13 | slack.habiat.sh: slack.habitat.sh 14 | 15 | # Keep Original GitHub Issues, PRs, Apps 16 | github.com/habitat-sh/habitat/issues: github.com/habitat-sh/habitat/issues 17 | github.com/habitat-sh/habitat/pull: github.com/habitat-sh/habitat/pull 18 | https://github.com/apps/habitat-builder: https://github.com/apps/habitat-builder 19 | 20 | github.com/habitat-sh/habitat-operator/issues: github.com/habitat-sh/habitat-operator/issues 21 | github.com/habitat-sh/habitat-operator/pull: github.com/habitat-sh/habitat-operator/pull 22 | 23 | # Currently don't touch bintray 24 | # https://api.bintray.com/content/habitat: https://api.bintray.com/content/habitat 25 | # https://api.bintray.com/packages/habitat: https://api.bintray.com/packages/habitat 26 | 27 | # Chef Packages: 28 | https://packages.chef.io/files/habitat/$version: https://github/biome-sh/biome/releases/download/bio-$version 29 | 30 | The Habitat Maintainers: The Biome Maintainers 31 | humans@habitat.sh: humans@biome.sh 32 | 33 | # Github Source 34 | habitat-sh/rust-zmq: habitat-sh/rust-zmq 35 | habitat-sh/ipc-channel: habitat-sh/ipc-channel 36 | habitat-sh/nitox: habitat-sh/nitox 37 | habitat-sh/core-plans: habitat-sh/core-plans 38 | habitat-sh/rust-nats: habitat-sh/rust-nats 39 | habitat-sh/prost: habitat-sh/prost 40 | habitat-sh/retry: habitat-sh/retry 41 | 42 | # Source code 43 | https://github.com/habitat-sh/habitat: https://github.com/biome-sh/biome 44 | https://raw.githubusercontent.com/habitat-sh/habitat/: https://raw.githubusercontent.com/biome-sh/biome/ 45 | 'github.com:habitat-sh/habitat': 'github.com:biome-sh/biome' 46 | 47 | # Remove chef licenses checks from OSS Version 48 | 'license::accept_license(ui)?;': '' 49 | 'if license_exists() ': 'if true ' 50 | 'license::check_for_license_acceptance_and_prompt(ui)?;': '' 51 | 'https://brand.chef.io/images/habitat/logos': 'https://biome.sh/images/biome/logos' 52 | 53 | # BLDR.TOML constants 54 | components/launcher/habitat: components/launcher/habitat 55 | components/builder-api-proxy/habitat: components/builder-api-proxy/habitat 56 | components/builder-api/habitat: components/builder-api/habitat 57 | components/builder-jobsrv/habitat: components/builder-jobsrv/habitat 58 | components/builder-worker/habitat: components/builder-worker/habitat 59 | components/builder-minio/habitat: components/builder-minio/habitat 60 | 61 | # Dev Plans 62 | /habitat-dev: /habitat-dev 63 | "--exclude='habitat'": "--exclude='habitat'" 64 | 65 | # Translate constants 66 | pkg_origin=core: pkg_origin=biome 67 | '$pkg_origin = "core"': '$pkg_origin = "biome"' 68 | '$pkg_origin="core"': '$pkg_origin="biome"' 69 | pkg_name=hab: pkg_name=bio 70 | pkg_path_for hab: pkg_path_for bio 71 | 72 | habirails: biorails 73 | core/hab hab: biome/bio bio 74 | hab --version: bio --version 75 | core/hab: biome/bio 76 | core\hab: biome\\bio 77 | core-hab: biome-bio 78 | hab.exe: bio.exe 79 | core/windows-service: biome/windows-service 80 | 81 | https://habitat-sh.github.io/habitat-operator/helm/charts/stable: https://habitat-sh.github.io/habitat-operator/helm/charts/stable 82 | habitat-operator: habitat-operator 83 | 84 | ':habicat:': ':habicat:' 85 | ':hab:': ':bio:' 86 | 87 | # Docker Studios (biome org has already taken. use biomesh) 88 | 'const DOCKER_IMAGE: &str = "habitat/default-studio"': 'const DOCKER_IMAGE: &str = "biomesh/default-studio"' 89 | 'const DOCKER_WINDOWS_IMAGE: &str = "habitat/win-studio"': 'const DOCKER_WINDOWS_IMAGE: &str = "biomesh/win-studio"' 90 | 91 | 'GITHUB_ORG := habitat-sh': 'GITHUB_ORG := biome-sh' 92 | 'DOCKER_ORG := habitat': 'DOCKER_ORG := biomesh' 93 | 94 | 95 | habitat/devshell: biomesh/devshell 96 | 97 | # Make plans use habitat 98 | habitat/plan.sh: habitat/plan.sh 99 | habitat/x86_64-darwin: habitat/x86_64-darwin 100 | habitat/plan.ps1: habitat/plan.ps1 101 | habitat/hooks: habitat/hooks 102 | habitat\hooks: habitat\\hooks 103 | habitat/config: habitat/config 104 | habitat\config: habitat\\config 105 | habitat/default.toml: habitat/default.toml 106 | habitat\default.toml: habitat\\default.toml 107 | PLAN_CONTEXT/habitat: PLAN_CONTEXT/habitat 108 | PLAN_CONTEXT\habitat: PLAN_CONTEXT\\habitat 109 | rootfs/hab: rootfs/hab 110 | FS_ROOT/hab: FS_ROOT/hab 111 | 'plan_path = "habitat"': 'plan_path = "habitat"' 112 | 113 | # Preserve path joining 114 | ' .join("hab")': ' .join("hab")' 115 | 116 | 'ctx.bin_path().join("hab")': 'ctx.bin_path().join("bio")' 117 | 'Path::new(&*FS_ROOT_PATH).join("hab")': 'Path::new(&*FS_ROOT_PATH).join("hab")' 118 | 'PathBuf::from(&*FS_ROOT_PATH).join("hab")': 'PathBuf::from(&*FS_ROOT_PATH).join("hab")' 119 | 'rootfs.join("hab")': 'rootfs.join("hab")' 120 | 'HAB_ROOT_PATH:=/hab': 'HAB_ROOT_PATH:=/hab' 121 | 'pub const ROOT_PATH: &str = "hab";': 'pub const ROOT_PATH: &str = "hab";' 122 | 123 | # After replacement all occurances hab_pkgs_path will be bio_pkgs_path 124 | 'tar_builder.append_dir_all("hab", hab_pkgs_path);': 'tar_builder.append_dir_all("hab", bio_pkgs_path);' 125 | 126 | # Supervisor compatibility habitat <-> biome 127 | 'const HABITAT_SUBJECT: &str = "habitat";': 'const HABITAT_SUBJECT: &str = "habitat";' 128 | 'const SERVICE_STARTED_SUBJECT: &str = "habitat.event.service_started";': 'const SERVICE_STARTED_SUBJECT: &str = "habitat.event.service_started";' 129 | 'const SERVICE_STOPPED_SUBJECT: &str = "habitat.event.service_stopped";': 'const SERVICE_STOPPED_SUBJECT: &str = "habitat.event.service_stopped";' 130 | 'const SERVICE_UPDATE_STARTED_SUBJECT: &str = "habitat.event.service_update_started";': 'const SERVICE_UPDATE_STARTED_SUBJECT: &str = "habitat.event.service_update_started";' 131 | 'const HEALTHCHECK_SUBJECT: &str = "habitat.event.healthcheck";': 'const HEALTHCHECK_SUBJECT: &str = "habitat.event.healthcheck";' 132 | 'let topic = "habitat".to_string();': 'let topic = "habitat".to_string();' 133 | 134 | # Event protocol compatibility 135 | chef.habitat.supervisor.event: chef.habitat.supervisor.event 136 | 137 | # builder compatibility 138 | habitat-builder-artifact-store: habitat-builder-artifact-store 139 | 140 | # builder front 141 | habKeysPipe: bioKeysPipe 142 | 143 | # Builder plan path compatibility (looks hacky, I know) 144 | 'default_plan_path() -> PathBuf { PathBuf::from("habitat")': 'default_plan_path() -> PathBuf { PathBuf::from("habitat")' 145 | 'p.ends_with("habitat")': 'p.ends_with("habitat")' 146 | ' p.push("habitat");': ' p.push("habitat");' 147 | 148 | # Builder DB compatibility 149 | hab_client: hab_client 150 | 151 | # Preserve habitat user for compatibility 152 | 'hab:x:42:42:root:/:/bin/sh': 'hab:x:42:42:root:/:/bin/sh' 153 | 'hab:x:42:hab': 'hab:x:42:hab' 154 | 'RUN useradd --user-group hab': 'RUN useradd --user-group hab' 155 | 'run_user="hab': 'run_user="hab' 156 | 157 | 'svc_user=hab': 'svc_user=hab' 158 | 'svc_user="hab"': 'svc_user="hab"' 159 | 'svc_user = "hab"': 'svc_user = "hab"' 160 | '"svc_user": "hab"': '"svc_user": "hab"' 161 | 162 | 'user = \"hab\"': 'user = \"hab\"' 163 | 'Cow::Owned("hab".into())': 'Cow::Owned("hab".into())' 164 | 165 | '/id -u hab': '/id -u hab' 166 | 'useradd hab': 'useradd hab' 167 | 'adduser hab': 'adduser hab' 168 | 'adduser --group hab': 'adduser --group hab' 169 | 'useradd -g hab hab': 'useradd -g hab hab' 170 | 'useradd --system --no-create-home hab': 'useradd --system --no-create-home hab' 171 | 'adduser --system hab': 'adduser --system hab' 172 | 173 | "User 'hab' already exists": "User 'hab' already exists" 174 | "Group 'hab' already exists": "Group 'hab' already exists" 175 | 176 | '`hab` user': '`hab` user' 177 | # This command, replace 178 | 'hab user key': 'bio user key' 179 | 'hab user help': 'bio user help' 180 | # Otherwise preserve 181 | 'hab user': 'hab user' 182 | 'SVC_USER or SVC_GROUP is hab': 'SVC_USER or SVC_GROUP is hab' 183 | 'DEFAULT_USER: &str = "hab"': 'DEFAULT_USER: &str = "hab"' 184 | 'The user to run the service as. The default is hab.': 'The user to run the service as. The default is hab.' 185 | ' .unwrap_or_else(|| String::from("hab"));': ' .unwrap_or_else(|| String::from("hab"));' 186 | '("root", "hab")': '("root", "hab")' 187 | '("hab", "hab")': '("hab", "hab")' 188 | '("hab", "root")': '("hab", "root")' 189 | '("hab", _)': '("hab", _)' 190 | 'EtcPasswdEntry::new("hab"': 'EtcPasswdEntry::new("hab"' 191 | 192 | # Preserve habitat group for compatibility 193 | 'svc_group=hab': 'svc_group=hab' 194 | 'svc_group="hab"': 'svc_group="hab"' 195 | 'svc_group = "hab"': 'svc_group = "hab"' 196 | '"svc_group": "hab"': '"svc_group": "hab"' 197 | 198 | 'groupadd --system hab': 'groupadd --system hab' 199 | 'addgroup --system hab': 'addgroup --system hab' 200 | 'hab group': 'hab group' 201 | 'DEFAULT_GROUP: &str = "hab"': 'DEFAULT_GROUP: &str = "hab"' 202 | 'The group to run the service as. The default is hab.': 'The group to run the service as. The default is hab.' 203 | ' .unwrap_or_else(|| String::from("hab"));': ' .unwrap_or_else(|| String::from("hab"));' 204 | 'EtcGroupEntry::group_with_users("hab"': 'EtcGroupEntry::group_with_users("hab"' 205 | 'gid, &["hab"]': 'gid, &["hab"]' 206 | 207 | 'hab:hab': 'hab:hab' 208 | 209 | # Mostly for builder 210 | 'initdb -U hab': 'initdb -U hab' 211 | 'psql -U hab': 'psql -U hab' 212 | 'user = "hab"': 'user = "hab"' 213 | 'all hab': 'all hab' 214 | 'replication hab': 'replication hab' 215 | 'user: String::from("hab")': 'user: String::from("hab")' 216 | 'useradd -r -U hab': 'useradd -r -U hab' 217 | "name = 'hab'": "name = 'hab'" 218 | "password = 'hab'": "password = 'hab'" 219 | 220 | Chef Habitat: Biome 221 | Habitat: Biome 222 | habitat: biome 223 | habiat: biome 224 | Habiat: Biome 225 | 226 | # Convert paths explicitly 227 | cli/hab/bldr: cli/bio/bldr 228 | cli/hab/cli: cli/bio/cli 229 | cli/hab/config: cli/bio/config 230 | cli/hab/file: cli/bio/file 231 | cli/hab/license: cli/bio/license 232 | cli/hab/origin: cli/bio/origin 233 | cli/hab/pkg: cli/bio/pkg 234 | cli/hab/plan: cli/bio/plan 235 | cli/hab/ring: cli/bio/ring 236 | cli/hab/studio: cli/bio/studio 237 | cli/hab/sup: cli/bio/sup 238 | cli/hab/svc: cli/bio/svc 239 | cli/hab/tests: cli/bio/tests 240 | cli/hab/user: cli/bio/user 241 | cli/hab/util: cli/bio/util 242 | 243 | # Make some biome path compatible 244 | hab/bin: hab/bin 245 | hab/etc: hab/etc 246 | hab/launcher: hab/launcher 247 | hab/sup: hab/sup 248 | hab/svc: hab/svc 249 | hab/pkgs: hab/pkgs 250 | hab/cache: hab/cache 251 | hab/studios: hab/studios 252 | ~/.hab: ~/.hab 253 | 254 | # Also windows 255 | hab\bin: hab\\bin 256 | hab\etc: hab\\etc 257 | hab\launcher: hab\\launcher 258 | hab\sup: hab\\sup 259 | hab\svc: hab\\svc 260 | hab\pkgs: hab\\pkgs 261 | hab\cache: hab\\cache 262 | hab\studios: hab\\studios 263 | 264 | # Double slash in quotes translate too 265 | hab\\bin: hab\\\\bin 266 | hab\\etc: hab\\\\etc 267 | hab\\launcher: hab\\\\launcher 268 | hab\\sup: hab\\\\sup 269 | hab\\svc: hab\\\\svc 270 | hab\\pkgs: hab\\\\pkgs 271 | hab\\cache: hab\\\\cache 272 | hab\\studios: hab\\\\studios 273 | 274 | hab/hab: hab/hab 275 | ' hab ': ' bio ' 276 | 277 | # Translate all habs beacause 278 | # Replacing hab -> bio is danger (word `unreachable` will be `unreacbiole` ) 279 | hab/: bio/ 280 | hab\: bio\\ 281 | hab\\: bio\\\\ 282 | 283 | # Assigments 284 | =hab: =bio 285 | hab=: bio= 286 | '= hab': '= bio' 287 | 'hab =': 'bio =' 288 | '= "hab"': '= "bio"' 289 | 290 | # Relative path 291 | ../hab: ../bio 292 | 293 | # Variables 294 | _hab: _bio 295 | hab_: bio_ 296 | -hab: -bio 297 | hab-: bio- 298 | '&hab': '&bio' 299 | '$hab': '$bio' 300 | '${hab}': '${bio}' 301 | 302 | /hab: /bio 303 | bin/hab: bin/bio 304 | 'use hab': 'use bio' 305 | 'hab::': 'bio::' 306 | 307 | # String occurances 308 | '"hab"': '"bio"' 309 | "'hab'": "'bio'" 310 | ' hab': ' bio' 311 | # Not always works somewhy? 312 | '`hab': '`bio' 313 | 314 | 315 | 'hab ': 'bio ' 316 | 317 | 'hab:': 'bio:' 318 | hab\: bio\\ 319 | \hab: \\bio 320 | ':hab': ':bio' 321 | '[hab]': '[bio]' 322 | .hab: .bio 323 | 324 | # Delete some files which safe to ignore 325 | deletes: 326 | # We're not going to support public site now 327 | - www 328 | 329 | # Silence mentions 330 | - .mailmap 331 | - .mention-bot 332 | - CODEOWNERS 333 | 334 | # Development will go in upstream 335 | - CONTRIBUTING.md 336 | - MAINTAINERS.md 337 | - RELEASE.md 338 | - CODE_OF_CONDUCT.md 339 | - CHANGELOG_FAKE.md 340 | - .github 341 | - .mailmap 342 | 343 | # Remove stock travis and other ci-s 344 | - .travis.yml 345 | - .expeditor 346 | - .buildkite 347 | - tools/one-of-release 348 | - e2e_local.sh 349 | - e2e_local.ps1 350 | - e2e_env 351 | 352 | # I don't know what is it 353 | - manifest.json 354 | - manifest.json.asc 355 | 356 | # Cargo.lock is wrong for us 357 | - Cargo.lock 358 | 359 | # Excludes from patching contents 360 | excludes: 361 | - README.md 362 | - CHANGELOG.md 363 | - LICENSE 364 | - UX_PRINCIPLES.md 365 | - components/core/tests/fixtures/unhappyhumans-possums-8.1.4-20160427165340-x86_64-linux.hart 366 | - support/bash_completion.sh 367 | -------------------------------------------------------------------------------- /examples/habitat.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # Most uniq patterns should go first 4 | # !!! ORDER IS IMPORTANT !!! 5 | patterns: 6 | 7 | # Keep Original Sites 8 | www.habitat.sh: www.habitat.sh 9 | bldr.habitat.sh: bldr.habitat.sh 10 | forums.habitat.sh: forums.habitat.sh 11 | slack.habiat.sh: slack.habitat.sh 12 | 13 | # Keep Original GitHub Issues, PRs, Apps 14 | github.com/habitat-sh/habitat/issues: github.com/habitat-sh/habitat/issues 15 | github.com/habitat-sh/habitat/pull: github.com/habitat-sh/habitat/pull 16 | https://github.com/apps/habitat-builder: https://github.com/apps/habitat-builder 17 | 18 | github.com/habitat-sh/habitat-operator/issues: github.com/habitat-sh/habitat-operator/issues 19 | github.com/habitat-sh/habitat-operator/pull: github.com/habitat-sh/habitat-operator/pull 20 | 21 | # Currently don't touch bintray 22 | # https://api.bintray.com/content/habitat: https://api.bintray.com/content/habitat 23 | # https://api.bintray.com/packages/habitat: https://api.bintray.com/packages/habitat 24 | 25 | # Chef Packages: 26 | https://packages.chef.io/files/habitat/$version: https://github/biome-sh/biome/releases/download/bio-$version 27 | 28 | The Habitat Maintainers: The Biome Maintainers 29 | humans@habitat.sh: humans@biome.sh 30 | 31 | # Github Source 32 | habitat-sh/rust-zmq: habitat-sh/rust-zmq 33 | habitat-sh/ipc-channel: habitat-sh/ipc-channel 34 | habitat-sh/nitox: habitat-sh/nitox 35 | habitat-sh/core-plans: habitat-sh/core-plans 36 | habitat-sh/rust-nats: habitat-sh/rust-nats 37 | habitat-sh/prost: habitat-sh/prost 38 | habitat-sh/retry: habitat-sh/retry 39 | 40 | # Source code 41 | https://github.com/habitat-sh/habitat: https://github.com/biome-sh/biome 42 | https://raw.githubusercontent.com/habitat-sh/habitat/: https://raw.githubusercontent.com/biome-sh/biome/ 43 | 'github.com:habitat-sh/habitat': 'github.com:biome-sh/biome' 44 | 45 | # Remove chef licenses checks from OSS Version 46 | 'license::accept_license(ui)?;': '' 47 | 'if license_exists() ': 'if true ' 48 | 'license::check_for_license_acceptance_and_prompt(ui)?;': '' 49 | 'https://brand.chef.io/images/habitat/logos': 'https://biome.sh/images/biome/logos' 50 | 51 | # BLDR.TOML constants 52 | components/launcher/habitat: components/launcher/habitat 53 | components/builder-api-proxy/habitat: components/builder-api-proxy/habitat 54 | components/builder-api/habitat: components/builder-api/habitat 55 | components/builder-jobsrv/habitat: components/builder-jobsrv/habitat 56 | components/builder-worker/habitat: components/builder-worker/habitat 57 | components/builder-minio/habitat: components/builder-minio/habitat 58 | 59 | # Dev Plans 60 | /habitat-dev: /habitat-dev 61 | "--exclude='habitat'": "--exclude='habitat'" 62 | 63 | # Translate constants 64 | pkg_origin=core: pkg_origin=biome 65 | '$pkg_origin = "core"': '$pkg_origin = "biome"' 66 | '$pkg_origin="core"': '$pkg_origin="biome"' 67 | pkg_name=hab: pkg_name=bio 68 | pkg_path_for hab: pkg_path_for bio 69 | 70 | habirails: biorails 71 | core/hab hab: biome/bio bio 72 | hab --version: bio --version 73 | core/hab: biome/bio 74 | core\hab: biome\\bio 75 | core-hab: biome-bio 76 | hab.exe: bio.exe 77 | core/windows-service: biome/windows-service 78 | 79 | https://habitat-sh.github.io/habitat-operator/helm/charts/stable: https://habitat-sh.github.io/habitat-operator/helm/charts/stable 80 | habitat-operator: habitat-operator 81 | 82 | ':habicat:': ':habicat:' 83 | ':hab:': ':bio:' 84 | 85 | # Docker Studios (biome org has already taken. use biomesh) 86 | 'const DOCKER_IMAGE: &str = "habitat/default-studio"': 'const DOCKER_IMAGE: &str = "biomesh/default-studio"' 87 | 'const DOCKER_WINDOWS_IMAGE: &str = "habitat/win-studio"': 'const DOCKER_WINDOWS_IMAGE: &str = "biomesh/win-studio"' 88 | 89 | 'GITHUB_ORG := habitat-sh': 'GITHUB_ORG := biome-sh' 90 | 'DOCKER_ORG := habitat': 'DOCKER_ORG := biomesh' 91 | 92 | 93 | habitat/devshell: biomesh/devshell 94 | 95 | # Make plans use habitat 96 | habitat/plan.sh: habitat/plan.sh 97 | habitat/x86_64-darwin: habitat/x86_64-darwin 98 | habitat/plan.ps1: habitat/plan.ps1 99 | habitat/hooks: habitat/hooks 100 | habitat\hooks: habitat\\hooks 101 | habitat/config: habitat/config 102 | habitat\config: habitat\\config 103 | habitat/default.toml: habitat/default.toml 104 | habitat\default.toml: habitat\\default.toml 105 | PLAN_CONTEXT/habitat: PLAN_CONTEXT/habitat 106 | PLAN_CONTEXT\habitat: PLAN_CONTEXT\\habitat 107 | rootfs/hab: rootfs/hab 108 | FS_ROOT/hab: FS_ROOT/hab 109 | 'plan_path = "habitat"': 'plan_path = "habitat"' 110 | 111 | # Preserve path joining 112 | ' .join("hab")': ' .join("hab")' 113 | 114 | 'ctx.bin_path().join("hab")': 'ctx.bin_path().join("bio")' 115 | 'Path::new(&*FS_ROOT_PATH).join("hab")': 'Path::new(&*FS_ROOT_PATH).join("hab")' 116 | 'PathBuf::from(&*FS_ROOT_PATH).join("hab")': 'PathBuf::from(&*FS_ROOT_PATH).join("hab")' 117 | 'rootfs.join("hab")': 'rootfs.join("hab")' 118 | 'HAB_ROOT_PATH:=/hab': 'HAB_ROOT_PATH:=/hab' 119 | 'pub const ROOT_PATH: &str = "hab";': 'pub const ROOT_PATH: &str = "hab";' 120 | 121 | # After replacement all occurances hab_pkgs_path will be bio_pkgs_path 122 | 'tar_builder.append_dir_all("hab", hab_pkgs_path);': 'tar_builder.append_dir_all("hab", bio_pkgs_path);' 123 | 124 | # Supervisor compatibility habitat <-> biome 125 | 'const HABITAT_SUBJECT: &str = "habitat";': 'const HABITAT_SUBJECT: &str = "habitat";' 126 | 'const SERVICE_STARTED_SUBJECT: &str = "habitat.event.service_started";': 'const SERVICE_STARTED_SUBJECT: &str = "habitat.event.service_started";' 127 | 'const SERVICE_STOPPED_SUBJECT: &str = "habitat.event.service_stopped";': 'const SERVICE_STOPPED_SUBJECT: &str = "habitat.event.service_stopped";' 128 | 'const SERVICE_UPDATE_STARTED_SUBJECT: &str = "habitat.event.service_update_started";': 'const SERVICE_UPDATE_STARTED_SUBJECT: &str = "habitat.event.service_update_started";' 129 | 'const HEALTHCHECK_SUBJECT: &str = "habitat.event.healthcheck";': 'const HEALTHCHECK_SUBJECT: &str = "habitat.event.healthcheck";' 130 | 'let topic = "habitat".to_string();': 'let topic = "habitat".to_string();' 131 | 132 | # Event protocol compatibility 133 | chef.habitat.supervisor.event: chef.habitat.supervisor.event 134 | 135 | # builder compatibility 136 | habitat-builder-artifact-store: habitat-builder-artifact-store 137 | 138 | # builder front 139 | habKeysPipe: bioKeysPipe 140 | 141 | # Builder plan path compatibility (looks hacky, I know) 142 | 'default_plan_path() -> PathBuf { PathBuf::from("habitat")': 'default_plan_path() -> PathBuf { PathBuf::from("habitat")' 143 | 'p.ends_with("habitat")': 'p.ends_with("habitat")' 144 | ' p.push("habitat");': ' p.push("habitat");' 145 | 146 | # Builder DB compatibility 147 | hab_client: hab_client 148 | 149 | # Preserve habitat user for compatibility 150 | 'hab:x:42:42:root:/:/bin/sh': 'hab:x:42:42:root:/:/bin/sh' 151 | 'hab:x:42:hab': 'hab:x:42:hab' 152 | 'RUN useradd --user-group hab': 'RUN useradd --user-group hab' 153 | 'run_user="hab': 'run_user="hab' 154 | 155 | 'svc_user=hab': 'svc_user=hab' 156 | 'svc_user="hab"': 'svc_user="hab"' 157 | 'svc_user = "hab"': 'svc_user = "hab"' 158 | '"svc_user": "hab"': '"svc_user": "hab"' 159 | 160 | 'user = \"hab\"': 'user = \"hab\"' 161 | 'Cow::Owned("hab".into())': 'Cow::Owned("hab".into())' 162 | 163 | '/id -u hab': '/id -u hab' 164 | 'useradd hab': 'useradd hab' 165 | 'adduser hab': 'adduser hab' 166 | 'adduser --group hab': 'adduser --group hab' 167 | 'useradd -g hab hab': 'useradd -g hab hab' 168 | 'useradd --system --no-create-home hab': 'useradd --system --no-create-home hab' 169 | 'adduser --system hab': 'adduser --system hab' 170 | 171 | "User 'hab' already exists": "User 'hab' already exists" 172 | "Group 'hab' already exists": "Group 'hab' already exists" 173 | 174 | '`hab` user': '`hab` user' 175 | # This command, replace 176 | 'hab user key': 'bio user key' 177 | 'hab user help': 'bio user help' 178 | # Otherwise preserve 179 | 'hab user': 'hab user' 180 | 'SVC_USER or SVC_GROUP is hab': 'SVC_USER or SVC_GROUP is hab' 181 | 'DEFAULT_USER: &str = "hab"': 'DEFAULT_USER: &str = "hab"' 182 | 'The user to run the service as. The default is hab.': 'The user to run the service as. The default is hab.' 183 | ' .unwrap_or_else(|| String::from("hab"));': ' .unwrap_or_else(|| String::from("hab"));' 184 | '("root", "hab")': '("root", "hab")' 185 | '("hab", "hab")': '("hab", "hab")' 186 | '("hab", "root")': '("hab", "root")' 187 | '("hab", _)': '("hab", _)' 188 | 'EtcPasswdEntry::new("hab"': 'EtcPasswdEntry::new("hab"' 189 | 190 | # Preserve habitat group for compatibility 191 | 'svc_group=hab': 'svc_group=hab' 192 | 'svc_group="hab"': 'svc_group="hab"' 193 | 'svc_group = "hab"': 'svc_group = "hab"' 194 | '"svc_group": "hab"': '"svc_group": "hab"' 195 | 196 | 'groupadd --system hab': 'groupadd --system hab' 197 | 'addgroup --system hab': 'addgroup --system hab' 198 | 'hab group': 'hab group' 199 | 'DEFAULT_GROUP: &str = "hab"': 'DEFAULT_GROUP: &str = "hab"' 200 | 'The group to run the service as. The default is hab.': 'The group to run the service as. The default is hab.' 201 | ' .unwrap_or_else(|| String::from("hab"));': ' .unwrap_or_else(|| String::from("hab"));' 202 | 'EtcGroupEntry::group_with_users("hab"': 'EtcGroupEntry::group_with_users("hab"' 203 | 'gid, &["hab"]': 'gid, &["hab"]' 204 | 205 | 'hab:hab': 'hab:hab' 206 | 207 | # Mostly for builder 208 | 'initdb -U hab': 'initdb -U hab' 209 | 'psql -U hab': 'psql -U hab' 210 | 'user = "hab"': 'user = "hab"' 211 | 'all hab': 'all hab' 212 | 'replication hab': 'replication hab' 213 | 'user: String::from("hab")': 'user: String::from("hab")' 214 | 'useradd -r -U hab': 'useradd -r -U hab' 215 | "name = 'hab'": "name = 'hab'" 216 | "password = 'hab'": "password = 'hab'" 217 | 218 | Chef Habitat: Biome 219 | Habitat: Biome 220 | habitat: biome 221 | habiat: biome 222 | Habiat: Biome 223 | 224 | # Convert paths explicitly 225 | cli/hab/bldr: cli/bio/bldr 226 | cli/hab/cli: cli/bio/cli 227 | cli/hab/config: cli/bio/config 228 | cli/hab/file: cli/bio/file 229 | cli/hab/license: cli/bio/license 230 | cli/hab/origin: cli/bio/origin 231 | cli/hab/pkg: cli/bio/pkg 232 | cli/hab/plan: cli/bio/plan 233 | cli/hab/ring: cli/bio/ring 234 | cli/hab/studio: cli/bio/studio 235 | cli/hab/sup: cli/bio/sup 236 | cli/hab/svc: cli/bio/svc 237 | cli/hab/tests: cli/bio/tests 238 | cli/hab/user: cli/bio/user 239 | cli/hab/util: cli/bio/util 240 | 241 | # Make some biome path compatible 242 | hab/bin: hab/bin 243 | hab/etc: hab/etc 244 | hab/launcher: hab/launcher 245 | hab/sup: hab/sup 246 | hab/svc: hab/svc 247 | hab/pkgs: hab/pkgs 248 | hab/cache: hab/cache 249 | hab/studios: hab/studios 250 | ~/.hab: ~/.hab 251 | 252 | # Also windows 253 | hab\bin: hab\\bin 254 | hab\etc: hab\\etc 255 | hab\launcher: hab\\launcher 256 | hab\sup: hab\\sup 257 | hab\svc: hab\\svc 258 | hab\pkgs: hab\\pkgs 259 | hab\cache: hab\\cache 260 | hab\studios: hab\\studios 261 | 262 | # Double slash in quotes translate too 263 | hab\\bin: hab\\\\bin 264 | hab\\etc: hab\\\\etc 265 | hab\\launcher: hab\\\\launcher 266 | hab\\sup: hab\\\\sup 267 | hab\\svc: hab\\\\svc 268 | hab\\pkgs: hab\\\\pkgs 269 | hab\\cache: hab\\\\cache 270 | hab\\studios: hab\\\\studios 271 | 272 | hab/hab: hab/hab 273 | ' hab ': ' bio ' 274 | 275 | # Translate all habs beacause 276 | # Replacing hab -> bio is danger (word `unreachable` will be `unreacbiole` ) 277 | hab/: bio/ 278 | hab\: bio\\ 279 | hab\\: bio\\\\ 280 | 281 | # Assigments 282 | =hab: =bio 283 | hab=: bio= 284 | '= hab': '= bio' 285 | 'hab =': 'bio =' 286 | '= "hab"': '= "bio"' 287 | 288 | # Relative path 289 | ../hab: ../bio 290 | 291 | # Variables 292 | _hab: _bio 293 | hab_: bio_ 294 | -hab: -bio 295 | hab-: bio- 296 | '&hab': '&bio' 297 | '$hab': '$bio' 298 | '${hab}': '${bio}' 299 | 300 | /hab: /bio 301 | bin/hab: bin/bio 302 | 'use hab': 'use bio' 303 | 'hab::': 'bio::' 304 | 305 | # String occurances 306 | '"hab"': '"bio"' 307 | "'hab'": "'bio'" 308 | ' hab': ' bio' 309 | # Not always works somewhy? 310 | '`hab': '`bio' 311 | 312 | 313 | 'hab ': 'bio ' 314 | 315 | 'hab:': 'bio:' 316 | hab\: bio\\ 317 | \hab: \\bio 318 | ':hab': ':bio' 319 | '[hab]': '[bio]' 320 | .hab: .bio 321 | 322 | # Delete some files which safe to ignore 323 | deletes: 324 | # We're not going to support public site now 325 | - www 326 | 327 | # Silence mentions 328 | - .mailmap 329 | - .mention-bot 330 | - CODEOWNERS 331 | 332 | # Development will go in upstream 333 | - CONTRIBUTING.md 334 | - MAINTAINERS.md 335 | - RELEASE.md 336 | - CODE_OF_CONDUCT.md 337 | - CHANGELOG_FAKE.md 338 | - .github 339 | - .mailmap 340 | 341 | # Remove stock travis and other ci-s 342 | - .travis.yml 343 | - .expeditor 344 | - .buildkite 345 | - tools/one-of-release 346 | - e2e_env 347 | - e2e_local.ps1 348 | - e2e_local_raw_command.sh 349 | - e2e_local.sh 350 | 351 | # I don't know what is it 352 | - manifest.json 353 | - manifest.json.asc 354 | 355 | # Excludes from patching contents 356 | excludes: 357 | - README.md 358 | - CHANGELOG.md 359 | - LICENSE 360 | - UX_PRINCIPLES.md 361 | - components/core/tests/fixtures/unhappyhumans-possums-8.1.4-20160427165340-x86_64-linux.hart 362 | - support/bash_completion.sh 363 | -------------------------------------------------------------------------------- /forkman-patch-git: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | FORKMAN_CONFIG=".forkman.yaml" 4 | FORKMAN_UPSTREAM_BRANCH="upstream/master" 5 | FORKMAN_MAIN_BRANCH="forkman-raw" 6 | FORKMAN_PATCH_BRANCH="forkman-$(date +%F)" 7 | 8 | 9 | while getopts 'c:u:m:hb' flag; do 10 | case "${flag}" in 11 | c) FORKMAN_CONFIG="${OPTARG}" ;; 12 | u) FORKMAN_UPSTREAM_BRANCH="${OPTARG}" ;; 13 | m) FORKMAN_MAIN_BRANCH="${OPTARG}" ;; 14 | b) FORKMAN_BATCH_MODE="y" ;; 15 | *) 16 | echo "Usage:" 17 | echo "$0 [-c FORKMAN_CONFIG] [-u FORKMAN_UPSTREAM_BRANCH] [-m FORKMAN_MAIN_BRANCH]" 18 | echo " -c FORKMAN_CONFIG Path to a yaml dictionary. Default: .forkman.yaml" 19 | echo " -u FORKMAN_UPSTREAM_BRANCH An upstream branch to patch. Default: upstream/master" 20 | echo " -m FORKMAN_MAIN_BRANCH Branch with patches. Default: forkman-raw" 21 | echo " -b Run without asking questions" 22 | echo "" 23 | echo "Run patch from root of a git repository:" 24 | echo "Do not modify FORKMAN_MAIN_BRANCH branch. Just keep and update it forever." 25 | exit 1 26 | ;; 27 | esac 28 | done 29 | 30 | 31 | if [ ! -f "$FORKMAN_CONFIG" ]; then 32 | echo "Config was not found: $FORKMAN_CONFIG" 33 | exit 1 34 | fi 35 | 36 | if [ ! -d ".git" ]; then 37 | echo "Not in root of a git repository: $(pwd)" 38 | exit 1 39 | fi 40 | 41 | if [ -z "$FORKMAN_UPSTREAM_BRANCH" ]; then 42 | echo "Upstream branch should not be empty" 43 | echo "Usually it should look like upstream/master" 44 | exit 1 45 | fi 46 | 47 | # You likely have committed your .forkman.yaml so before switch we should preserve it outside 48 | FORKMAN_TMP_CONFIG="$(mktemp -t forkman.XXXX)" 49 | cp "$FORKMAN_CONFIG" "$FORKMAN_TMP_CONFIG" 50 | 51 | if [ -z "$FORKMAN_BATCH_MODE" ]; then 52 | echo "WARN: Reseting index and HEAD. Press enter to continue or CTRL+C to abort" 53 | read 54 | fi 55 | 56 | echo "Resetting index and cleaning" 57 | git reset --hard HEAD 58 | git clean -fd 59 | 60 | # echo "Making patch branch: $FORKMAN_PATCH_BRANCH" 61 | git checkout -B "$FORKMAN_PATCH_BRANCH" "$FORKMAN_UPSTREAM_BRANCH" 62 | 63 | echo "Applying forkman:" 64 | forkman --config "$FORKMAN_TMP_CONFIG" --repo . 65 | 66 | echo "Rework patches on main branch: $FORKMAN_MAIN_BRANCH" 67 | echo "WARN: This branch is expected to keep clean and raw" 68 | git reset "$FORKMAN_MAIN_BRANCH" 69 | 70 | echo "We are on clean state so safe to add literally everything" 71 | git add . 72 | 73 | git commit -m "Backport $FORKMAN_UPSTREAM_BRANCH at $(git rev-parse "$FORKMAN_UPSTREAM_BRANCH")" 74 | git checkout "$FORKMAN_MAIN_BRANCH" 75 | 76 | # Should be always fast-forward 77 | git merge --ff-only "$FORKMAN_PATCH_BRANCH" 78 | git branch -D "$FORKMAN_PATCH_BRANCH" 79 | 80 | echo "$FORKMAN_MAIN_BRANCH was built." 81 | -------------------------------------------------------------------------------- /forkman.rb: -------------------------------------------------------------------------------- 1 | require 'mixlib/cli' 2 | require 'yaml' 3 | require 'fileutils' 4 | require 'filemagic' 5 | 6 | STDOUT.sync = true 7 | 8 | class ForkMan 9 | include Mixlib::CLI 10 | 11 | banner "#{__FILE__} (options)" 12 | 13 | option :config, 14 | long: '--config YAML', 15 | required: true, 16 | proc: ->(x) { File.expand_path(x) }, 17 | description: 'YAML-based configuration file' 18 | 19 | option :repo, 20 | long: '--repo DIR', 21 | required: true, 22 | proc: ->(x) { File.expand_path(x) }, 23 | description: 'Directory with GIT project' 24 | 25 | option :steps, 26 | long: '--steps NUM', 27 | default: 1_000_000, 28 | proc: ->(x) { Integer(x) }, 29 | description: 'How many patterns to apply. Default: 1_000_000' 30 | 31 | option :preserve_tokens, 32 | long: '--[no-]preserve-tokens', 33 | boolean: true, 34 | default: false, 35 | description: 'Stop translating and leave tokens' 36 | 37 | def run 38 | parse_options 39 | 40 | yaml = YAML.load_file(File.expand_path(config[:config])) 41 | 42 | config[:patterns] = (yaml['patterns'] || {}).to_a 43 | config[:excludes] = yaml['excludes'] || [] 44 | config[:deletes] = yaml['deletes'] || [] 45 | 46 | Dir.chdir(config[:repo]) do 47 | FileUtils.rm_rf(config[:deletes]) unless config[:deletes].empty? 48 | translate_filenames 49 | translate_contents 50 | end 51 | 52 | word, translate = config[:patterns][config[:steps] - 1] 53 | puts "Last applied: #{word} -> #{translate}." 54 | end 55 | 56 | def translate_filenames 57 | each_repo_file do |file| 58 | new_file = file.dup 59 | 60 | # We must tokenize all patterns BEFORE replace them with a new text 61 | each_dict_pattern do |word, translate, token| 62 | new_file.gsub!(word, token) 63 | rescue => e 64 | puts "[#{file}] Error tokinization: #{word}" 65 | raise e 66 | end 67 | 68 | # After all tokens have been generated it is time to translate 69 | each_dict_pattern do |word, translate, token| 70 | new_file.gsub!(token, translate) 71 | rescue => e 72 | puts "[#{file}] Error translating: #{translate}" 73 | raise e 74 | end 75 | 76 | next if new_file == file 77 | 78 | puts "Binary file renamed: #{file} -> #{new_file}" unless FileMagic.fm.file(file) =~ /text/ 79 | 80 | FileUtils.mkdir_p(File.dirname(new_file)) 81 | `git mv "#{file}" "#{new_file}"` 82 | end 83 | end 84 | 85 | def translate_contents 86 | each_repo_file do |file| 87 | next if File.symlink?(file) 88 | 89 | file_content = File.read(file) 90 | hash = file_content.hash 91 | 92 | # We must tokenize all pattern BEFORE replace it with new text 93 | each_dict_pattern do |word, translate, token| 94 | file_content.gsub!(word, token) 95 | rescue => e 96 | puts "[#{file}] Error tokinization: #{word}" 97 | raise e 98 | end 99 | 100 | # After all tokens have been generated it is time to translate 101 | each_dict_pattern do |word, translate, token| 102 | file_content.gsub!(token, translate) 103 | rescue => e 104 | puts "[#{file}] Error translating: #{translate}" 105 | raise e 106 | end 107 | 108 | next if hash == file_content.hash 109 | 110 | puts "Binary content replaced: #{file}" unless FileMagic.fm.file(file) =~ /text/ 111 | File.write(file, file_content) 112 | end 113 | end 114 | 115 | def each_repo_file 116 | Dir.glob('**/*', File::FNM_DOTMATCH) do |file| 117 | next if file =~ %r|^.git/| 118 | next if File.directory?(file) 119 | 120 | next if config[:excludes].include?(file) 121 | 122 | yield file 123 | end 124 | end 125 | 126 | def each_dict_pattern 127 | config[:patterns].each_with_index do |pattern, index| 128 | return if index >= config[:steps] 129 | 130 | token = "TOKEN_%07d" % index 131 | 132 | # For debug preserve tokens otherwise - replace 133 | if config[:preserve_tokens] 134 | yield(pattern[0], token, token) 135 | else 136 | yield(pattern[0], pattern[1], token) 137 | end 138 | end 139 | end 140 | end 141 | 142 | ForkMan.new.run 143 | -------------------------------------------------------------------------------- /habitat/plan.sh: -------------------------------------------------------------------------------- 1 | # shellcheck shell=bash 2 | 3 | pkg_origin=jsirex 4 | pkg_name=forkman 5 | pkg_version="0.2.2" 6 | 7 | pkg_description="Repository Fork Manager" 8 | pkg_maintainer="Yauhen Artsiukhou " 9 | pkg_license=("MIT") 10 | 11 | pkg_deps=( 12 | core/file 13 | core/bash 14 | core/ruby3_4 15 | ) 16 | 17 | pkg_build_deps=( 18 | core/file 19 | core/gcc 20 | core/make 21 | ) 22 | 23 | pkg_bin_dirs=(bin) 24 | 25 | do_prepare() { 26 | bundle config set --global build.ruby-filemagic --with-magic-dir="$(pkg_path_for core/file)" 27 | 28 | # shellcheck disable=SC2154 29 | cp -v Gemfile "$CACHE_PATH/Gemfile.biome" 30 | } 31 | 32 | do_build() { 33 | return 0 34 | } 35 | 36 | do_install() { 37 | # shellcheck disable=SC2154 38 | bundle install --gemfile "$CACHE_PATH/Gemfile.biome" --path "$pkg_prefix/rubygems" 39 | 40 | mkdir -p "${pkg_prefix}/lib" 41 | cp forkman.rb "${pkg_prefix}/lib" 42 | 43 | ruby_wrapper 44 | install forkman-patch-git "${pkg_prefix}/bin" 45 | fix_interpreter "${pkg_prefix}/bin/forkman-patch-git" core/bash bin/bash 46 | } 47 | 48 | # Wraps regular ruby script according to current GEM_HOME with appropriate LOAD_PATH 49 | ruby_wrapper() { 50 | # shellcheck disable=SC2155 51 | local ruby_path="$(pkg_path_for core/ruby3_4)/bin/ruby" 52 | local gem_path="$pkg_prefix/rubygems/ruby/3.4.0+0" 53 | local cli_path="$pkg_prefix/lib/forkman.rb" 54 | local cli_name="forkman" 55 | 56 | cat < "$pkg_prefix/bin/$cli_name" 57 | #!$ruby_path 58 | 59 | # This is automatically generate wrapper for $pkg_name $pkg_version 60 | 61 | ENV['GEM_HOME'] = '$gem_path' 62 | ENV['GEM_PATH'] = '$gem_path' 63 | 64 | Gem::clear_paths 65 | 66 | # Make sure absolute path 67 | LIBDIRS = File.join('$gem_path', 'gems', '*','lib') 68 | 69 | Dir.glob(LIBDIRS).each do |libdir| 70 | \$LOAD_PATH.unshift(libdir) unless \$LOAD_PATH.include?(libdir) 71 | end 72 | 73 | load "$cli_path" 74 | EOF 75 | chmod +x "$pkg_prefix/bin/$cli_name" 76 | } 77 | --------------------------------------------------------------------------------