├── .github └── workflows │ ├── image.yml │ └── main.yml ├── .gitignore ├── .idea └── .gitignore ├── .rubocop.yml ├── CHANGELOG.md ├── Dockerfile ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── bin ├── console └── setup ├── containers.conf ├── exe └── pgpm ├── lib ├── pgpm.rb └── pgpm │ ├── arch.rb │ ├── aspects │ └── inheritance_tracker.rb │ ├── cache.rb │ ├── commands.rb │ ├── contrib │ ├── amcheck.rb │ ├── auth_delay.rb │ ├── auto_explain.rb │ ├── basebackup_to_shell.rb │ ├── btree_gist.rb │ ├── dblink.rb │ ├── pgcrypto.rb │ ├── plpython3u.rb │ └── postgres_fdw.rb │ ├── deb │ ├── Dockerfile │ ├── builder.rb │ ├── pbuilder_install_script.sh │ ├── scripts │ │ ├── install_default_control.sh │ │ ├── pg_config.sh │ │ └── prepare_artifacts.sh │ ├── spec.rb │ └── templates │ │ ├── changelog.erb │ │ ├── control.erb │ │ ├── copyright.erb │ │ ├── files.erb │ │ └── rules.erb │ ├── on_demand_file.rb │ ├── os.rb │ ├── os │ ├── darwin.rb │ ├── debian.rb │ ├── linux.rb │ ├── red_hat.rb │ └── unix.rb │ ├── package.rb │ ├── package │ ├── abstract_package.rb │ ├── building.rb │ ├── contrib.rb │ ├── dependencies.rb │ ├── enumerating.rb │ ├── git.rb │ ├── git_hub.rb │ ├── initialization.rb │ ├── make.rb │ ├── metadata.rb │ ├── naming.rb │ ├── native.rb │ ├── packaging.rb │ ├── pgxn.rb │ ├── rust.rb │ ├── source.rb │ ├── subscripting.rb │ ├── version.rb │ ├── versioning.rb │ └── with_path.rb │ ├── podman.rb │ ├── postgres │ ├── distribution.rb │ └── redhat_based_pgdg.rb │ ├── rpm.rb │ ├── rpm │ ├── builder.rb │ ├── mock │ │ ├── config.rb │ │ ├── configs │ │ │ ├── rocky+epel-9-aarch64+pgdg.cfg │ │ │ └── rocky+epel-9-x86_64+pgdg.cfg │ │ └── operation.rb │ ├── scripts │ │ ├── pg_config.sh │ │ └── prepare_artifacts.sh │ └── spec.rb │ ├── scoped_object.rb │ └── version.rb ├── packages ├── acl.rb ├── age.rb ├── aggs_for_arrays.rb ├── aggs_for_vecs.rb ├── anon.rb ├── arraymath.rb ├── asn1oid.rb ├── aws_s3.rb ├── base36.rb ├── base62.rb ├── bgw_replstatus.rb ├── chkpass.rb ├── citus.rb ├── citus_columnar.rb ├── columnar.rb ├── count_distinct.rb ├── country.rb ├── credcheck.rb ├── cryptint.rb ├── currency.rb ├── data_historization.rb ├── db2_fdw.rb ├── dbt2.rb ├── ddl_historization.rb ├── ddlx.rb ├── ddsketch.rb ├── debversion.rb ├── decoder_raw.rb ├── decoderbufs.rb ├── duckdb_fdw.rb ├── emaj.rb ├── envvar.rb ├── explain_ui.rb ├── extra_window_functions.rb ├── faker.rb ├── financial.rb ├── firebird_fdw.rb ├── first_last_agg.rb ├── floatfile.rb ├── floatvec.rb ├── geoip.rb ├── gzip.rb ├── h3.rb ├── h3_postgis.rb ├── hdfs_fdw.rb ├── hll.rb ├── hstore_pllua.rb ├── hstore_plluau.rb ├── http.rb ├── hunspell_cs_cz.rb ├── hunspell_de_de.rb ├── hunspell_en_us.rb ├── hunspell_fr.rb ├── hunspell_ne_np.rb ├── hunspell_nl_nl.rb ├── hunspell_nn_no.rb ├── hunspell_pt_pt.rb ├── hunspell_ru_ru.rb ├── hunspell_ru_ru_aot.rb ├── hypopg.rb ├── icu_ext.rb ├── imgsmlr.rb ├── index_advisor.rb ├── ip4r.rb ├── jdbc_fdw.rb ├── jsquery.rb ├── kafka_fdw.rb ├── log_fdw.rb ├── logerrors.rb ├── login_hook.rb ├── lower_quantile.rb ├── md5hash.rb ├── meta.rb ├── mimeo.rb ├── mobilitydb.rb ├── mongo_fdw.rb ├── multicorn.rb ├── mysql_fdw.rb ├── noset.rb ├── numeral.rb ├── odbc_fdw.rb ├── ogr_fdw.rb ├── omnigres │ ├── extension_discovery.rb │ ├── omni.rb │ ├── omni_auth.rb │ ├── omni_aws.rb │ ├── omni_cloudevents.rb │ ├── omni_containers.rb │ ├── omni_http.rb │ ├── omni_httpc.rb │ ├── omni_httpd.rb │ ├── omni_id.rb │ ├── omni_json.rb │ ├── omni_ledger.rb │ ├── omni_manifest.rb │ ├── omni_mimetypes.rb │ ├── omni_os.rb │ ├── omni_polyfill.rb │ ├── omni_python.rb │ ├── omni_regex.rb │ ├── omni_schema.rb │ ├── omni_seq.rb │ ├── omni_session.rb │ ├── omni_sql.rb │ ├── omni_txn.rb │ ├── omni_types.rb │ ├── omni_var.rb │ ├── omni_vfs.rb │ ├── omni_vfs_types_v1.rb │ ├── omni_web.rb │ ├── omni_xml.rb │ ├── omni_yaml.rb │ ├── package.rb │ └── scripts │ │ └── generate_upgrade.sh ├── omnisketch.rb ├── oracle_fdw.rb ├── orafce.rb ├── pagevis.rb ├── passwordcheck_cracklib.rb ├── periods.rb ├── permuteseq.rb ├── pg_analytics.rb ├── pg_auditor.rb ├── pg_auth_mon.rb ├── pg_background.rb ├── pg_base58.rb ├── pg_bestmatch.rb ├── pg_bigm.rb ├── pg_bulkload.rb ├── pg_cardano.rb ├── pg_catcheck.rb ├── pg_cheat_funcs.rb ├── pg_checksums.rb ├── pg_crash.rb ├── pg_cron.rb ├── pg_dbms_job.rb ├── pg_dbms_lock.rb ├── pg_dbms_metadata.rb ├── pg_dirtyread.rb ├── pg_drop_events.rb ├── pg_duckdb.rb ├── pg_duration.rb ├── pg_extra_time.rb ├── pg_fact_loader.rb ├── pg_failover_slots.rb ├── pg_fio.rb ├── pg_fkpart.rb ├── pg_geohash.rb ├── pg_graphql.rb ├── pg_hashids.rb ├── pg_hashlib.rb ├── pg_hint_plan.rb ├── pg_html5_email_address.rb ├── pg_idkit.rb ├── pg_incremental.rb ├── pg_ivm.rb ├── pg_jobmon.rb ├── pg_jsonschema.rb ├── pg_later.rb ├── pg_math.rb ├── pg_mooncake.rb ├── pg_net.rb ├── pg_orphaned.rb ├── pg_parquet.rb ├── pg_partman.rb ├── pg_permissions.rb ├── pg_polyline.rb ├── pg_proctab.rb ├── pg_profile.rb ├── pg_protobuf.rb ├── pg_qualstats.rb ├── pg_rational.rb ├── pg_readme.rb ├── pg_readonly.rb ├── pg_relusage.rb ├── pg_repack.rb ├── pg_rrule.rb ├── pg_savior.rb ├── pg_search.rb ├── pg_session_jwt.rb ├── pg_show_plans.rb ├── pg_similarity.rb ├── pg_smtp_client.rb ├── pg_snakeoil.rb ├── pg_sphere.rb ├── pg_sqlog.rb ├── pg_squeeze.rb ├── pg_stat_kcache.rb ├── pg_stat_monitor.rb ├── pg_statement_rollback.rb ├── pg_store_plans.rb ├── pg_strom.rb ├── pg_summarize.rb ├── pg_task.rb ├── pg_tde.rb ├── pg_text_semver.rb ├── pg_tiktoken.rb ├── pg_tle.rb ├── pg_top.rb ├── pg_track_settings.rb ├── pg_upless.rb ├── pg_uuidv7.rb ├── pg_wait_sampling.rb ├── pg_xenophile.rb ├── pgaudit.rb ├── pgauditlogtofile.rb ├── pgautofailover.rb ├── pgbouncer_fdw.rb ├── pgcozy.rb ├── pgdd.rb ├── pgemailaddr.rb ├── pgextwlist.rb ├── pgfaceting.rb ├── pgfincore.rb ├── pgjwt.rb ├── pgl_ddl_deploy.rb ├── pglite_fusion.rb ├── pglogical.rb ├── pglogical_origin.rb ├── pglogical_ticker.rb ├── pgmemcache.rb ├── pgmeminfo.rb ├── pgml.rb ├── pgmp.rb ├── pgmq.rb ├── pgnodemx.rb ├── pgpcre.rb ├── pgpdf.rb ├── pgq.rb ├── pgqr.rb ├── pgroonga.rb ├── pgroonga_database.rb ├── pgrouting.rb ├── pgsmcrypto.rb ├── pgsodium.rb ├── pgsql_tweaks.rb ├── pgtap.rb ├── pgtt.rb ├── pguecc.rb ├── pgvector.rb ├── plan_filter.rb ├── pldbgapi.rb ├── pljava.rb ├── pllua.rb ├── plluau.rb ├── plpgsql_check.rb ├── plprofiler.rb ├── plproxy.rb ├── plprql.rb ├── plr.rb ├── plsh.rb ├── plv8.rb ├── pointcloud.rb ├── pointcloud_postgis.rb ├── powa.rb ├── pre_prepare.rb ├── prefix.rb ├── prioritize.rb ├── q3c.rb ├── quantile.rb ├── random.rb ├── rdkit.rb ├── redis.rb ├── redis_fdw.rb ├── repmgr.rb ├── roaringbitmap.rb ├── rum.rb ├── safeupdate.rb ├── schedoc.rb ├── semver.rb ├── sequential_uuids.rb ├── session_variable.rb ├── set_user.rb ├── shacrypt.rb ├── smlar.rb ├── sqlite_fdw.rb ├── sslutils.rb ├── supabase_vault.rb ├── supautils.rb ├── system_stats.rb ├── table_log.rb ├── table_version.rb ├── tdigest.rb ├── tds_fdw.rb ├── temporal_tables.rb ├── timeit.rb ├── timescale │ ├── timescaledb.rb │ └── timescaledb_apache2.rb ├── timescaledb_toolkit.rb ├── timeseries.rb ├── timestamp9.rb ├── toastinfo.rb ├── topn.rb ├── uint.rb ├── uint128.rb ├── unit.rb ├── uri.rb ├── url_encode.rb ├── vasco.rb ├── vchord.rb ├── vectorize.rb ├── vectorscale.rb ├── wal2json.rb ├── wal2mongo.rb ├── wrappers.rb ├── xxhash.rb ├── zhparser.rb └── zstd.rb ├── pgpm.gemspec ├── pigsty.rb ├── sig └── pgpm.rbs └── test ├── test_helper.rb ├── test_pgpm.rb └── test_pgpm_package_version.rb /.github/workflows/image.yml: -------------------------------------------------------------------------------- 1 | name: Container image 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | env: 9 | REGISTRY: ghcr.io 10 | IMAGE_NAME: ${{ github.repository }} 11 | 12 | jobs: 13 | build: 14 | 15 | strategy: 16 | matrix: 17 | platform: [ amd64, arm64 ] 18 | 19 | runs-on: ${{ fromJSON('["warp-ubuntu-2204-x64-4x", "warp-ubuntu-2204-arm64-16x"]')[matrix.platform == 'arm64'] }} 20 | name: Build container image 21 | 22 | permissions: 23 | contents: read 24 | packages: write 25 | # This is used to complete the identity challenge 26 | # with sigstore/fulcio when running outside of PRs. 27 | id-token: write 28 | 29 | steps: 30 | - uses: actions/checkout@v4 31 | 32 | - name: Set up Docker Buildx 33 | uses: docker/setup-buildx-action@v3 34 | with: 35 | driver-opts: | 36 | network=host 37 | 38 | - name: Log in to the Container registry 39 | uses: docker/login-action@v3 40 | with: 41 | registry: ${{ env.REGISTRY }} 42 | username: ${{ github.actor }} 43 | password: ${{ secrets.GITHUB_TOKEN }} 44 | 45 | - name: Extract metadata (tags, labels) for Docker 46 | id: meta 47 | uses: docker/metadata-action@v5 48 | with: 49 | images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} 50 | 51 | - name: Build and push Docker image 52 | id: push 53 | uses: docker/build-push-action@v6 54 | with: 55 | target: pgpm 56 | platforms: linux/${{ matrix.platform }} 57 | context: . 58 | push: true 59 | tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest-${{ matrix.platform }} 60 | labels: ${{ steps.meta.outputs.labels }} 61 | allow: security.insecure 62 | cache-from: type=gha,url=http://127.0.0.1:49160/ 63 | cache-to: type=gha,url=http://127.0.0.1:49160/,mode=max 64 | provenance: false 65 | 66 | 67 | manifest: 68 | 69 | needs: build 70 | runs-on: ubuntu-latest 71 | 72 | permissions: 73 | contents: read 74 | packages: write 75 | 76 | steps: 77 | - uses: actions/checkout@v3 78 | 79 | - name: Log in to the Container registry 80 | uses: docker/login-action@v3 81 | with: 82 | registry: ${{ env.REGISTRY }} 83 | username: ${{ github.actor }} 84 | password: ${{ secrets.GITHUB_TOKEN }} 85 | 86 | - name: Extract metadata (tags, labels) for Docker 87 | id: meta 88 | uses: docker/metadata-action@v5 89 | with: 90 | images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} 91 | 92 | - name: Create and push manifest images 93 | uses: Noelware/docker-manifest-action@master # or use a pinned version in the Releases tab 94 | with: 95 | inputs: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest 96 | images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest-amd64,${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest-arm64 97 | push: true 98 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Ruby 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | pull_request: 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | name: Ruby ${{ matrix.ruby }} 14 | strategy: 15 | matrix: 16 | ruby: 17 | - '3.3.5' 18 | - '3.4.1' 19 | 20 | steps: 21 | - uses: actions/checkout@v4 22 | - name: Set up Ruby 23 | uses: ruby/setup-ruby@v1 24 | with: 25 | ruby-version: ${{ matrix.ruby }} 26 | bundler-cache: true 27 | - name: Run the default task 28 | run: bundle exec rake 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /_yardoc/ 4 | /coverage/ 5 | /doc/ 6 | /pkg/ 7 | /spec/reports/ 8 | /tmp/ 9 | .idea 10 | Gemfile.lock -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | AllCops: 2 | TargetRubyVersion: 3.3 3 | 4 | Style/StringLiterals: 5 | EnforcedStyle: double_quotes 6 | 7 | Style/StringLiteralsInInterpolation: 8 | EnforcedStyle: double_quotes 9 | 10 | Style/FormatStringToken: 11 | EnforcedStyle: template 12 | 13 | ## Settings below are meant to be enabled (at least some of them) 14 | ## but in order to make rubocop useful first for correcting obvious things, 15 | ## they were disabled for the time being. TODO: review 16 | 17 | Style/Documentation: 18 | Enabled: false 19 | 20 | Metrics/MethodLength: 21 | Enabled: false 22 | 23 | Metrics/AbcSize: 24 | Enabled: false 25 | 26 | Metrics/ClassLength: 27 | Enabled: false 28 | 29 | Metrics/PerceivedComplexity: 30 | Enabled: false 31 | 32 | Metrics/CyclomaticComplexity: 33 | Enabled: false 34 | 35 | Naming/MethodParameterName: 36 | Enabled: false 37 | 38 | Layout/LineLength: 39 | Enabled: false 40 | 41 | Metrics/BlockLength: 42 | Enabled: false 43 | 44 | Naming/HeredocDelimiterNaming: 45 | Enabled: false 46 | 47 | Style/IfUnlessModifier: 48 | Enabled: false 49 | 50 | Style/ClassVars: 51 | Enabled: false 52 | 53 | Style/MultilineBlockChain: 54 | Enabled: false 55 | 56 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [Unreleased] 2 | 3 | ## [0.1.0] - 2024-10-04 4 | 5 | - Initial release 6 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax = docker/dockerfile:experimental 2 | 3 | # IMPORTANT: build it this way to allow for privileged execution 4 | # 5 | # Docker daemon config should have the entitlement 6 | # ```json 7 | # { "builder": {"Entitlements": {"security-insecure": true }} } 8 | # ``` 9 | # ``` 10 | # DOCKER_BUILDKIT=1 docker build --allow security.insecure -t pgpm:local /path/to/pgpm 11 | # ``` 12 | 13 | FROM fedora:41 AS pgpm 14 | 15 | RUN dnf -y install rpmlint ruby ruby-devel mock git gcc zlib-devel libyaml-devel 16 | # Pre-initialize mock roots 17 | COPY lib/pgpm/rpm/mock/configs configs 18 | RUN --security=insecure for file in $(find configs -name '*.cfg'); do for ver in "17 16 15 14 13"; \ 19 | do mock --config-opts pgdg_version=$ver $file --init ; done; done 20 | 21 | 22 | # Pre-initialize gems. It may need an update later, but it'll save us time 23 | RUN mkdir -p /pgpm 24 | COPY lib /pgpm/lib 25 | COPY Gemfile /pgpm 26 | COPY pgpm.gemspec /pgpm 27 | COPY exe /pgpm/exe 28 | RUN chmod +x /pgpm/exe/* 29 | RUN cd /pgpm && gem build && gem install -n /usr/local/bin pgpm*.gem 30 | RUN rm -rf pgpm 31 | 32 | COPY containers.conf /etc/containers/containers.conf 33 | 34 | RUN rm -rf /run/containers/storage /run/libpod 35 | 36 | ENV QEMU_CPU max 37 | 38 | 39 | FROM pgpm AS pgpm-dev 40 | 41 | COPY . /pgpm 42 | RUN cd /pgpm && bundle install 43 | RUN rm -rf /pgpm 44 | 45 | VOLUME /pgpm 46 | WORKDIR /pgpm -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://rubygems.org" 4 | 5 | # Specify your gem's dependencies in pgpm.gemspec 6 | gemspec 7 | 8 | gem "rake", "~> 13.0" 9 | 10 | gem "minitest", "~> 5.16" 11 | 12 | gem "rubocop", "~> 1.21" 13 | 14 | gem "debug", "~> 1.9" 15 | 16 | gem "rbs", "~> 3.6" 17 | 18 | gem "csv", "~> 3.3" 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Postgres.pm 2 | 3 | **Postgres.pm** (aka **pgpm**) is a streamlined package manager designed to simplify the process of building and 4 | distributing Postgres extensions and packages. 5 | 6 | ## Key objectives 7 | 8 |
9 | Platform independence 10 | 11 | Postgres.pm is designed to deliver Postgres extensions 12 | in native packaging (such as RPM, DEB, OCI images, etc.) 13 | to support the broad variety of usage patterns. 14 | 15 |
16 | 17 | > [!NOTE] 18 | > Early release is targeting RHEL-based distributions using 19 | > official PGDG Postgres distributions with other options 20 | > coming up. 21 | 22 |
23 | Low-effort package maintenance 24 | 25 | Postgres.pm embraces the concept of inferences: based 26 | on given information, it'll figure out how to build the package 27 | if it fits into a set of pre-defined rules. 28 | 29 | New versions are automatically picked up and recognized. 30 | 31 | Package definition can be as simple as this – with no routine 32 | maintenace on new releases: 33 | 34 | ```ruby 35 | 36 | class Pgvector < Pgpm::Package 37 | github "pgvector/pgvector" 38 | end 39 | ``` 40 | 41 |
42 | 43 |
44 | Package definition flexibility 45 | 46 | Packages definitions are defined in Ruby, allowing for near-infinite 47 | flexibility of their definition when necessary. 48 | 49 | This allows us to accomodate non-standard build and installation procedures 50 | with ease. 51 |
52 | 53 | --- 54 | 55 | ### Current Status 56 | 57 | We are preparing to start publishing RPM packages publicly soon. It's possible to build included packages manually. 58 | 59 | 60 | ### Development 61 | 62 | To build the packages, use the [exe/pgpm](exe/pgpm) script. 63 | 64 | Example: 65 | 66 | ```sh 67 | ./exe/pgpm build pgvector 68 | ``` 69 | 70 | ## pgpm build command 71 | 72 | ``` 73 | Usage: 74 | pgpm build PACKAGES... 75 | 76 | Arguments: 77 | PACKAGES # Package names (can include version with @, e.g., pgvector@1.0.0) 78 | 79 | Options: 80 | --pkgdir=VALUE # Directory to load packages from (default: "packages" if directory exists) 81 | --os=VALUE # OS name (default: auto-detected) 82 | --arch=VALUE # Target architecture (default: host architecture) 83 | --pgdist=VALUE # Target Postgres distribution (default: "pgdg") 84 | --pgver=VALUE # Target Postgres version (default: latest supported version) 85 | ``` 86 | 87 | Examples: 88 | 89 | ```sh 90 | # Build specific version 91 | pgpm build pgvector@1.0.0 92 | 93 | # Build for specific Postgres version 94 | pgpm build pgvector --pgver=15 95 | 96 | # Build multiple packages 97 | pgpm build pgvector pg_cron 98 | 99 | # Build from custom package directory 100 | pgpm build pgvector --pkgdir=custom/packages 101 | ``` 102 | 103 | ### Running pgpm build command via Official Docker Image 104 | 105 | Pull the official Docker image: 106 | 107 | ```sh 108 | docker pull ghcr.io/postgres-pm/pgpm:latest 109 | ``` 110 | 111 | You can use the following command to build the packages: 112 | 113 | ```sh 114 | docker run --rm -it ghcr.io/postgres-pm/pgpm:latest pgpm build pgvector 115 | ``` 116 | 117 | If using the development version (pgpm-dev stage), you can mount the current directory to the container: 118 | 119 | ```sh 120 | docker run --rm -it -v $(pwd):/pgpm ghcr.io/postgres-pm/pgpm:latest pgpm build pgvector 121 | ``` 122 | 123 | ### Building the Docker Image 124 | 125 | To build the Docker image, use the following command: 126 | 127 | ```sh 128 | # Build and load the image into local Docker daemon 129 | docker buildx build --load --allow security.insecure -t pgpm:local . 130 | ``` 131 | 132 | To use insecure builder, you can run the following commands: 133 | 134 | ```sh 135 | docker buildx create --name insecure-builder --driver-opt env.BUILDKIT_STEP_LOG_MAX_SIZE=-1 --buildkitd-flags '--allow-insecure-entitlement security.insecure' 136 | docker buildx use insecure-builder 137 | env DOCKER_BUILDKIT=1 docker build --allow security.insecure -t pgpm:local . 138 | ``` 139 | 140 | Later, you can use the builder by running: 141 | 142 | ```sh 143 | env DOCKER_BUILDKIT=1 docker build --builder=insecure-builder --allow security.insecure -t pgpm:local . 144 | ``` 145 | 146 | To run the image, use the following command: 147 | 148 | ```sh 149 | # If using the base pgpm image 150 | docker run --rm -it pgpm:local pgpm build pgvector 151 | 152 | # If using the development version (pgpm-dev stage) 153 | docker run --rm -it -v $(pwd):/pgpm pgpm:local ./exe/pgpm build pgvector 154 | ``` 155 | 156 | To remove the builder, run the following command: 157 | 158 | ```sh 159 | docker buildx rm insecure-builder 160 | ``` 161 | 162 | To remove the image, run the following command: 163 | 164 | ```sh 165 | docker rmi pgpm:local 166 | docker rmi ghcr.io/postgres-pm/pgpm:latest 167 | ``` 168 | 169 | ### Troubleshooting 170 | 171 | #### Podman invocations terminate with exit code 137 172 | 173 | Make sure your machine has enough RAM. For `podman-machine` you might want to adjust it 174 | with 175 | 176 | ```shell 177 | podman machine stop 178 | podman machine set -m 16384 # for 16GB 179 | podman machine start 180 | ``` 181 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "bundler/gem_tasks" 4 | require "minitest/test_task" 5 | 6 | Minitest::TestTask.create 7 | 8 | require "rubocop/rake_task" 9 | 10 | RuboCop::RakeTask.new 11 | 12 | task default: %i[test rubocop] 13 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require "bundler/setup" 5 | require "pgpm" 6 | 7 | # You can add fixtures and/or initialization code here to make experimenting 8 | # with your gem easier. You can also use a different console, if you like. 9 | 10 | require "irb" 11 | IRB.start(__FILE__) 12 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install 7 | 8 | # Do any other automated setup that you need to do here 9 | -------------------------------------------------------------------------------- /containers.conf: -------------------------------------------------------------------------------- 1 | [containers] 2 | netns="host" 3 | userns="host" 4 | ipcns="host" 5 | utsns="host" 6 | cgroupns="host" 7 | cgroups="disabled" 8 | log_driver = "k8s-file" 9 | [engine] 10 | cgroup_manager = "cgroupfs" 11 | events_logger="file" 12 | runtime="crun" -------------------------------------------------------------------------------- /exe/pgpm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require "English" 5 | require "bundler/setup" 6 | require "pgpm" 7 | require "dry/cli" 8 | require "parallel" 9 | require "etc" 10 | 11 | module Pgpm 12 | module CLI 13 | module Commands 14 | extend Dry::CLI::Registry 15 | 16 | class Version < Dry::CLI::Command 17 | desc "Print version" 18 | 19 | def call(*) 20 | puts Pgpm::VERSION 21 | end 22 | end 23 | 24 | module SharedOptions 25 | def self.included(base) 26 | base.class_eval do 27 | option :pkgdir, type: :string, default: File.directory?("packages") ? "packages" : nil, desc: "Directory to load packages from" 28 | end 29 | end 30 | end 31 | 32 | class Build < Dry::CLI::Command 33 | desc "Build packages" 34 | 35 | include SharedOptions 36 | 37 | option :os, type: :string, default: Pgpm::OS.auto_detect&.name, desc: "OS name" 38 | option :arch, type: :string, default: Pgpm::Arch.host.name, desc: "Target architecture" 39 | option :pgdist, type: :string, default: "pgdg", desc: "Target Postgres distribution" 40 | option :pgver, type: :string, default: Pgpm::Postgres::Distribution.versions.last.to_s, desc: "Target Postgres version" 41 | option :path, type: :path, desc: "Override path to the source" 42 | argument :packages, type: :array, required: true, desc: "Package names" 43 | 44 | module ExtendedProc 45 | refine Proc do 46 | def and_then(callable) 47 | lambda do |*args| 48 | res1 = call(*args) 49 | res2 = callable.call(*args) 50 | return res1 + res2 if res1.is_a?(Array) && res2.is_a?(Array) 51 | 52 | res2 53 | end 54 | end 55 | end 56 | end 57 | 58 | using ExtendedProc 59 | 60 | # rubocop:disable Metrics/ParameterLists: 61 | def call(packages:, args: nil, os: nil, arch: nil, pgdist: nil, pgver: nil, pkgdir: nil, path: nil) 62 | _ = args 63 | _ = os 64 | _ = pgdist 65 | 66 | Pgpm.load_packages(pkgdir) 67 | 68 | # puts "There is no build support for OS distribution `#{os}`" 69 | # exit(1) 70 | pkgs = Parallel.flat_map(packages, in_threads: Etc.nprocessors) do |package| 71 | name, version = package.split("@") 72 | version ||= :latest 73 | p = Pgpm::Package[name] 74 | if p.nil? 75 | puts "Package #{name} not found" 76 | exit(1) 77 | end 78 | if p.contrib? 79 | puts "Can't build a contrib package" 80 | exit(1) 81 | end 82 | pkg = path.nil? ? p[version] : p.new(version).with_path(path) 83 | if pkg.nil? 84 | puts "Package #{name} with version #{version} not found" 85 | exit(1) 86 | end 87 | pkg 88 | end 89 | 90 | os = os ? Pgpm::OS.find(os) : Pgpm::OS.auto_detect 91 | arch = if arch 92 | Pgpm::Arch.new(arch) 93 | else 94 | Pgpm::Arch.host 95 | end 96 | 97 | pgver = Package::Version.new(pgver) 98 | matching_pgver = Postgres::Distribution.versions.sort.reverse.find { |v| v.satisfies?(">= #{pgver}") && v.satisfies?("< #{pgver.major + 1}") } 99 | unless matching_pgver 100 | puts "#{pgver} is not a known Postgres version" 101 | exit(1) 102 | end 103 | 104 | if os.is_a? Pgpm::OS::Debian 105 | puts "Building #{pkgs.map { |p| "#{p.name}@#{p.version}" }.join(", ")} for Postgres #{matching_pgver}" 106 | selected_pgdist = Postgres::RedhatBasedPgdg.new(matching_pgver.to_s) 107 | 108 | os.with_scope do 109 | arch.with_scope do 110 | selected_pgdist.with_scope do 111 | spec = nil 112 | pkgs.reduce(nil) do |_c, p| 113 | p = Pgpm::ScopedObject.new(p, os, arch) 114 | spec = p.to_deb_spec 115 | end 116 | builder = Pgpm::Deb::Builder.new(spec) 117 | builder.build 118 | end 119 | end 120 | end 121 | elsif os.is_a? Pgpm::OS::RedHat 122 | puts "Building #{pkgs.map { |p| "#{p.name}@#{p.version}" }.join(", ")} for Postgres #{matching_pgver}" 123 | selected_pgdist = Postgres::RedhatBasedPgdg.new(matching_pgver.to_s) 124 | 125 | os.with_scope do 126 | arch.with_scope do 127 | selected_pgdist.with_scope do 128 | pkgs = pkgs.flat_map(&:topologically_ordered_with_dependencies).uniq.reject(&:contrib?) 129 | 130 | b = pkgs.reduce(nil) do |c, p| 131 | if p.broken? 132 | puts "Can't build a broken package #{p.name}@#{p.version}" 133 | exit(1) 134 | end 135 | p = Pgpm::ScopedObject.new(p, os, arch) 136 | spec = p.to_rpm_spec 137 | builder = Pgpm::RPM::Builder.new(spec) 138 | src_builder = builder.source_builder 139 | p = c.nil? ? src_builder : c.and_then(src_builder) 140 | p.and_then(builder.versionless_builder) 141 | end 142 | 143 | srpms = b.call 144 | Pgpm::RPM::Builder.builder(srpms).call 145 | end 146 | end 147 | end 148 | else 149 | puts "#{os.name} is not a supported OS at this moment" 150 | exit(1) 151 | end 152 | end 153 | 154 | # rubocop:enable Metrics/ParameterLists: 155 | end 156 | 157 | class Search < Dry::CLI::Command 158 | include SharedOptions 159 | 160 | argument :query, type: :string, default: ".*", desc: "Search query" 161 | option :format, values: %w[text json], default: "text", desc: "Output format", aliases: ["-f"] 162 | 163 | def call(query:, args: nil, pkgdir: nil, format: nil) 164 | _ = args 165 | 166 | Pgpm.load_packages(pkgdir) 167 | 168 | query_regexp = Regexp.new(query, "i") 169 | if format == "json" 170 | puts "[" 171 | end 172 | 173 | Parallel.filter_map(Pgpm::Package, in_threads: Etc.nprocessors) do |p| 174 | next if p.contrib? 175 | 176 | found = p.all_searchable_texts.any? do |t| 177 | t =~ query_regexp 178 | end 179 | next unless found 180 | 181 | output = case format 182 | when "json" then Oj.dump({ 183 | name: p.package_name, 184 | summary: p.summary, 185 | description: p.description, 186 | license: p.license, 187 | versions: p.package_versions.map(&:to_s) 188 | }, mode: :strict) 189 | else 190 | "#{p.package_name}: #{p.description}" 191 | end 192 | puts output 193 | rescue StandardError 194 | warn "Error fetching #{p.package_name}: #{$ERROR_INFO.message}" 195 | end 196 | 197 | return unless format == "json" 198 | 199 | puts "]" 200 | end 201 | end 202 | 203 | register "version", Version, aliases: ["v", "-v", "--version"] 204 | register "build", Build 205 | register "search", Search 206 | end 207 | end 208 | end 209 | 210 | Dry::CLI.new(Pgpm::CLI::Commands).call 211 | -------------------------------------------------------------------------------- /lib/pgpm.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "zeitwerk" 4 | require "pathname" 5 | 6 | class CustomInflector < Zeitwerk::GemInflector 7 | def camelize(basename, _abspath) 8 | # Specify your custom logic here 9 | # This tells Zeitwerk that 'rpm' should be 'RPM' and 'os' should be 'OS' 10 | case basename 11 | when "rpm" 12 | "RPM" 13 | when "os" 14 | "OS" 15 | when "pgxn" 16 | "PGXN" 17 | else 18 | super 19 | end 20 | end 21 | end 22 | 23 | module Pgpm 24 | end 25 | 26 | loader = Zeitwerk::Loader.for_gem 27 | loader.inflector = CustomInflector.new(__FILE__) 28 | loader.enable_reloading 29 | loader.setup 30 | loader.eager_load 31 | 32 | define_method(:reload!) do 33 | loader.reload 34 | loader.eager_load 35 | end 36 | 37 | define_method(:load_packages) do |path = nil| 38 | path ||= Pathname(File.dirname(__FILE__)).join("..", "packages") 39 | pkg_loader = Zeitwerk::Registry.loaders.find { |l| l.dirs.include?(path.to_s) } 40 | return pkg_loader if pkg_loader 41 | 42 | pkg_loader = Zeitwerk::Loader.new 43 | pkg_loader.push_dir(path) 44 | pkg_loader.enable_reloading 45 | pkg_loader.setup 46 | pkg_loader.eager_load 47 | pkg_loader 48 | end 49 | -------------------------------------------------------------------------------- /lib/pgpm/arch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rbconfig" 4 | require "lspace" 5 | 6 | module Pgpm 7 | class Arch 8 | def self.host 9 | new(RbConfig::CONFIG["host_cpu"]) 10 | end 11 | 12 | def self.in_scope 13 | LSpace[:pgpm_target_arch] 14 | end 15 | 16 | def initialize(name) 17 | @name = name == "arm64" ? "aarch64" : name 18 | end 19 | 20 | attr_reader :name 21 | 22 | def with_scope(&block) 23 | LSpace.with(pgpm_target_arch: self) do 24 | block.yield 25 | end 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/pgpm/aspects/inheritance_tracker.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | module Aspects 5 | module InheritanceTracker 6 | module ClassMethods 7 | def all_subclasses 8 | subclasses + subclasses.flat_map(&:all_subclasses) 9 | end 10 | end 11 | 12 | def self.included(base_class) 13 | base_class.extend(ClassMethods) 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/pgpm/cache.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "xdg" 4 | 5 | module Pgpm 6 | class Cache 7 | def self.directory 8 | XDG.new.cache_home.join("postgres.pm") 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/pgpm/commands.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "lspace" 4 | 5 | module Pgpm 6 | module Commands 7 | class Abstract 8 | def to_s 9 | raise "abstract implementation" 10 | end 11 | end 12 | 13 | class Make < Abstract 14 | def initialize(*args) 15 | @args = args 16 | super() 17 | end 18 | 19 | def to_s 20 | command = "make" 21 | command += " %{?_smp_mflags}" if Pgpm::OS.in_scope.is_a?(Pgpm::OS::RedHat) 22 | command += " #{@args.join(" ")}" unless @args.empty? 23 | command 24 | end 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /lib/pgpm/contrib/amcheck.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | module Contrib 5 | class Amcheck < Pgpm::Package 6 | contrib_package 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/pgpm/contrib/auth_delay.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | module Contrib 5 | class AuthDelay < Pgpm::Package 6 | contrib_package 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/pgpm/contrib/auto_explain.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | module Contrib 5 | class AutoExplain < Pgpm::Package 6 | contrib_package 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/pgpm/contrib/basebackup_to_shell.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | module Contrib 5 | class BasebackupToShell < Pgpm::Package 6 | contrib_package 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/pgpm/contrib/btree_gist.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | module Contrib 5 | class BtreeGist < Pgpm::Package 6 | contrib_package 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/pgpm/contrib/dblink.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | module Contrib 5 | class Dblink < Pgpm::Package 6 | contrib_package 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/pgpm/contrib/pgcrypto.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | module Contrib 5 | class Pgcrypto < Pgpm::Package 6 | contrib_package 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/pgpm/contrib/plpython3u.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | module Contrib 5 | class Plpython3u < Pgpm::Package 6 | contrib_package 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/pgpm/contrib/postgres_fdw.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | module Contrib 5 | class PostgresFdw < Pgpm::Package 6 | contrib_package 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/pgpm/deb/Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax = docker/dockerfile:experimental 2 | 3 | # IMPORTANT: build it this way to allow for privileged execution 4 | # 5 | # Docker daemon config should have the entitlement 6 | # ```json 7 | # { "builder": {"Entitlements": {"security-insecure": true }} } 8 | # ``` 9 | # ``` 10 | # DOCKER_BUILDKIT=1 docker build --allow security.insecure -t IMAGE_NAME /path/to/pgpm 11 | # ``` 12 | 13 | # This Dockerfile is used to build a Debian image, which includes pbuilder and 14 | # pbuilder chroot image with basic dependendencies needed for building most 15 | # packages already pre-installed. 16 | 17 | FROM docker.io/library/debian 18 | 19 | MAINTAINER PGPM Debian Maintainer debian.maintainer@postgres.pm 20 | 21 | VOLUME /proc 22 | ARG DEBIAN_FRONTEND=noninteractive 23 | RUN apt update 24 | RUN apt install -y build-essential pbuilder fakeroot fakechroot 25 | RUN echo 'MIRRORSITE=http://deb.debian.org/debian' > /etc/pbuilderrc 26 | RUN echo 'AUTO_DEBSIGN=${AUTO_DEBSIGN:-no}' > /root/.pbuilderrc 27 | RUN echo 'HOOKDIR=/var/cache/pbuilder/hooks' >> /root/.pbuilderrc 28 | RUN --security=insecure pbuilder create 29 | 30 | COPY pbuilder_install_script.sh /root/pbuilder_install_script.sh 31 | RUN --security=insecure pbuilder execute --save-after-exec /root/pbuilder_install_script.sh 32 | -------------------------------------------------------------------------------- /lib/pgpm/deb/builder.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "English" 4 | require "debug" 5 | 6 | module Pgpm 7 | module Deb 8 | class Builder 9 | def initialize(spec) 10 | @spec = spec 11 | @container_name = "pgpm-debian_build-#{Time.now.to_i}_#{rand(10_000)}" 12 | @pgpm_dir = Dir.mktmpdir 13 | end 14 | 15 | def build 16 | pull_image 17 | start_container 18 | patch_pbuilder 19 | 20 | prepare_versioned_source 21 | generate_deb_src_files(:versioned) 22 | run_build(:versioned) 23 | copy_build_from_container(:versioned) 24 | 25 | prepare_default_source 26 | generate_deb_src_files(:default) 27 | run_build(:default) 28 | copy_build_from_container(:default) 29 | 30 | cleanup 31 | end 32 | 33 | private 34 | 35 | # Depends on postgres version and arch 36 | def image_name 37 | "quay.io/qount25/pgpm-debian-pg#{@spec.package.postgres_major_version}-#{@spec.arch}" 38 | end 39 | 40 | def prepare_versioned_source 41 | puts "Preparing build..." 42 | puts " Creating container dir structure..." 43 | Dir.mkdir "#{@pgpm_dir}/source-versioned" 44 | Dir.mkdir "#{@pgpm_dir}/out" 45 | 46 | puts " Downloading and unpacking sources to #{@pgpm_dir}" 47 | 48 | fn = nil 49 | @spec.sources.map do |src| 50 | srcfile = File.join(@pgpm_dir.to_s, src.name) 51 | File.write(srcfile, src.read) 52 | fn = src.name 53 | end 54 | 55 | system("tar -xf #{@pgpm_dir}/#{fn} -C #{@pgpm_dir}/source-versioned/") 56 | FileUtils.remove("#{@pgpm_dir}/#{fn}") 57 | 58 | untar_dir_entries = Dir.entries("#{@pgpm_dir}/source-versioned/").reject do |entry| 59 | [".", ".."].include?(entry) 60 | end 61 | 62 | if untar_dir_entries.size == 1 63 | entry = untar_dir_entries[0] 64 | if File.directory?("#{@pgpm_dir}/source-versioned/#{entry}") 65 | FileUtils.mv "#{@pgpm_dir}/source-versioned/#{entry}", "#{@pgpm_dir}/" 66 | FileUtils.remove_dir "#{@pgpm_dir}/source-versioned/" 67 | FileUtils.mv "#{@pgpm_dir}/#{entry}", "#{@pgpm_dir}/source-versioned" 68 | end 69 | end 70 | 71 | ["prepare_artifacts.sh"].each do |f| 72 | script_fn = File.expand_path("#{__dir__}/scripts/#{f}") 73 | FileUtils.cp script_fn, "#{@pgpm_dir}/source-versioned/" 74 | end 75 | end 76 | 77 | def prepare_default_source 78 | Dir.mkdir "#{@pgpm_dir}/source-default" 79 | 80 | # 1. All pbuilder builds are in /var/cache/pbuilder/build. At this point 81 | # there's only one build, but we don't know what the directory is named 82 | # (the name is usually some numbers). So we just pick the first (and only) 83 | # entry at this location and this is our build dir. 84 | pbuilds_dir = "/var/cache/pbuilder/build" 85 | cmd = "ls -U #{pbuilds_dir} | head -1" 86 | build_dir = `podman exec #{@container_name} /bin/bash -c '#{cmd}'`.strip 87 | puts "BUILD DIR IS: #{pbuilds_dir}/#{build_dir}" 88 | 89 | # 2. Determine the name of the .control file inside the versioned build 90 | deb_dir = "#{pbuilds_dir}/#{build_dir}/build/#{@spec.deb_pkg_name(:versioned)}-0/debian/#{@spec.deb_pkg_name(:versioned)}" 91 | control_fn = "#{deb_dir}/usr/share/postgresql/#{@spec.package.postgres_major_version}/extension/#{@spec.package.extension_name}--#{@spec.package.version}.control" 92 | 93 | # 3. Copy .control file to the source-default dir 94 | puts "Copying #{control_fn} into /root/pgpm/source-default/" 95 | target_control_fn = "/root/pgpm/source-default/#{@spec.package.extension_name}.control" 96 | cmd = "cp #{control_fn} #{target_control_fn}" 97 | system("podman exec #{@container_name} /bin/bash -c '#{cmd}'") 98 | 99 | ["install_default_control.sh"].each do |fn| 100 | script_fn = File.expand_path("#{__dir__}/scripts/#{fn}") 101 | FileUtils.cp script_fn, "#{@pgpm_dir}/source-default/" 102 | end 103 | end 104 | 105 | def pull_image 106 | puts "Checking if podman image exists..." 107 | # Check if image exists 108 | system("podman image exists #{image_name}") 109 | if $CHILD_STATUS.to_i.positive? # image doesn't exist -- pull image from a remote repository 110 | puts " No. Pulling image #{image_name}..." 111 | system("podman pull #{image_name}") 112 | else 113 | puts " Yes, image #{image_name} already exists! OK" 114 | end 115 | end 116 | 117 | def generate_deb_src_files(pkg_type = :versioned) 118 | puts "Generating debian files..." 119 | Dir.mkdir "#{@pgpm_dir}/source-#{pkg_type}/debian" 120 | %i[changelog control copyright files rules].each do |f| 121 | puts " -> #{@pgpm_dir}/source-#{pkg_type}/debian/#{f}" 122 | File.write "#{@pgpm_dir}/source-#{pkg_type}/debian/#{f}", @spec.generate(f, pkg_type) 123 | end 124 | File.chmod 0o740, "#{@pgpm_dir}/source-#{pkg_type}/debian/rules" # rules file must be executable 125 | end 126 | 127 | def start_container 128 | # podman create options 129 | create_opts = " -v #{@pgpm_dir}:/root/pgpm" 130 | create_opts += ":z" if selinux_enabled? 131 | create_opts += " --privileged --tmpfs /tmp" 132 | create_opts += " --name #{@container_name} #{image_name}" 133 | 134 | puts " Creating and starting container #{@container_name} & running pbuilder" 135 | system("podman create -it #{create_opts}") 136 | exit(1) if $CHILD_STATUS.to_i.positive? 137 | system("podman start #{@container_name}") 138 | exit(1) if $CHILD_STATUS.to_i.positive? 139 | end 140 | 141 | # Prevents clean-up after pbuilder finishes. There's no option 142 | # in pbuilder to do it, so we have to patch it manually. The issue is 143 | # with pbuilder not being able to delete some directories (presumably, 144 | # due to directory names starting with ".") and returning error. 145 | # 146 | # This little patch avoids the error by returning from the python cleanup 147 | # function early -- because the package itself is built successfully and 148 | # we don't actually care that pbuilder is unable to clean something up. 149 | # The container is going to be removed anyway, so it's even less work as 150 | # a result. 151 | def patch_pbuilder 152 | cmd = "sed -E -i \"s/(^function clean_subdirectories.*$)/\\1\\n return/g\" /usr/lib/pbuilder/pbuilder-modules" 153 | system("podman exec #{@container_name} /bin/bash -c '#{cmd}'") 154 | end 155 | 156 | def run_build(pkg_type = :versioned) 157 | dsc_fn = "#{@spec.deb_pkg_name(pkg_type)}_0-1.dsc" 158 | deb_fn = "#{@spec.deb_pkg_name(pkg_type)}_0-1_#{@spec.arch}.deb" 159 | 160 | cmds = [] 161 | cmds << "dpkg-buildpackage --build=source -d" # -d flag helps with dependencies error 162 | cmds << "fakeroot pbuilder build ../#{dsc_fn}" 163 | cmds << "mv /var/cache/pbuilder/result/#{deb_fn} /root/pgpm/out/" 164 | 165 | puts " Building package with pbuilder..." 166 | cmds.each do |cmd| 167 | system("podman exec -w /root/pgpm/source-#{pkg_type} #{@container_name} /bin/bash -c '#{cmd}'") 168 | exit(1) if $CHILD_STATUS.to_i.positive? 169 | end 170 | end 171 | 172 | def copy_build_from_container(pkg_type = :versioned) 173 | puts "Copying .deb file from podman container into current directory..." 174 | deb_fn = "#{@spec.deb_pkg_name(pkg_type)}_0-1_#{@spec.arch}.deb" 175 | deb_copy_fn = "#{@spec.deb_pkg_name(pkg_type)}_#{@spec.arch}.deb" 176 | FileUtils.cp("#{@pgpm_dir}/out/#{deb_fn}", "#{Dir.pwd}/#{deb_copy_fn}") 177 | end 178 | 179 | def cleanup 180 | puts "Cleaning up..." 181 | 182 | puts " Stopping destroying podman container: #{@container_name}" 183 | system("podman container stop #{@container_name}") 184 | system("podman container rm #{@container_name}") 185 | 186 | # Remove temporary files 187 | # 188 | # Make sure @pgpm_dir starts with "/tmp/" or we may accidentally 189 | # delete something everything! You can never be sure! 190 | if @pgpm_dir.start_with?("/tmp/") 191 | puts " Removing temporary files in #{@pgpm_dir}" 192 | FileUtils.rm_rf(@pgpm_dir) 193 | else 194 | puts "WARNING: will not remove temporary files, strange path: \"#{@pgpm_dir}\"" 195 | end 196 | end 197 | 198 | # Needed because SELinux requires :z suffix for mounted directories to 199 | # be accessible -- otherwise we get "Permission denied" when cd into a 200 | # mounted dir inside the container. 201 | def selinux_enabled? 202 | # This returns true or false by itself 203 | system("sestatus | grep 'SELinux status' | grep -o 'enabled'") 204 | end 205 | end 206 | end 207 | end 208 | -------------------------------------------------------------------------------- /lib/pgpm/deb/pbuilder_install_script.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | apt update 3 | DEBIAN_FRONTEND=noninteractive apt -y install build-essential curl lsb-release ca-certificates 4 | 5 | ### PostgreSQL installation 6 | # 7 | install -d /usr/share/postgresql-common/pgdg 8 | curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc 9 | 10 | # Create the repository configuration file: 11 | sh -c 'echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' 12 | 13 | # Update the package lists: 14 | apt update 15 | 16 | # Install the latest version of PostgreSQL: 17 | # If you want a specific version, use 'postgresql-16' or similar instead of 'postgresql' 18 | apt -y install postgresql-17 postgresql-server-dev-17 postgresql-common 19 | # 20 | ### END OF PostgreSQL installation 21 | 22 | -------------------------------------------------------------------------------- /lib/pgpm/deb/scripts/install_default_control.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ext_dir="$PGPM_INSTALL_ROOT/$(pg_config --sharedir)/extension" 4 | control_fn="$ext_dir/$PGPM_EXTENSION_NAME.control" 5 | 6 | echo "Creating extension dir: $ext_dir" 7 | mkdir -p "$ext_dir" 8 | 9 | echo "Creating control file: $control_fn" 10 | cp "$PGPM_BUILDROOT/$PGPM_EXTENSION_NAME.control" "$ext_dir/" 11 | echo >> "$control_fn" 12 | echo "default_version = '$PGPM_EXTENSION_VERSION'" >> "$control_fn" 13 | -------------------------------------------------------------------------------- /lib/pgpm/deb/scripts/pg_config.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | # Ensure PG_CONFIG is set 4 | if [[ -z "$PG_CONFIG" ]]; then 5 | echo "Error: PG_CONFIG is not set." 6 | exit 1 7 | fi 8 | 9 | # Wrapper function for pg_config 10 | pg_config_wrapper() { 11 | "$PG_CONFIG" "$@" | while read -r line; do 12 | if [[ -n "$PGPM_REDIRECT_TO_BUILDROOT" && -f "$line" || -d "$line" ]]; then 13 | echo "$PGPM_INSTALL_ROOT$line" 14 | else 15 | echo "$line" 16 | fi 17 | done 18 | } 19 | 20 | # Call the wrapper function with the arguments passed to the script 21 | pg_config_wrapper "$@" 22 | -------------------------------------------------------------------------------- /lib/pgpm/deb/scripts/prepare_artifacts.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | #set -xe 4 | 5 | new_extension_so= 6 | 7 | PG_CONFIG="${PG_CONFIG:-"pg_config"}" 8 | 9 | install_root=$PGPM_INSTALL_ROOT 10 | 11 | for file in $(find $PGPM_BUILDROOT -name '*.so'); do 12 | filename=$(basename "$file") 13 | if [[ "$filename" == "${PGPM_EXTENSION_NAME}.so" ]]; then 14 | extension_so=$filename 15 | dir=$(dirname "$file") 16 | extension_dirname=${dir#"$PGPM_BUILDROOT"} 17 | new_extension_so=$PGPM_EXTENSION_NAME--$PGPM_EXTENSION_VERSION.so 18 | break 19 | fi 20 | done 21 | 22 | extdir=$install_root$($PG_CONFIG --sharedir)/extension 23 | 24 | # control files 25 | default_control=$extdir/$PGPM_EXTENSION_NAME.control 26 | versioned_control=$extdir/$PGPM_EXTENSION_NAME--$PGPM_EXTENSION_VERSION.control 27 | controls=("$default_control" "$versioned_control") 28 | 29 | function rename_so() { 30 | mv "$install_root$extension_dirname/$extension_so" \ 31 | "$install_root$extension_dirname/$new_extension_so" 32 | } 33 | 34 | function change_name_in_controls() { 35 | echo "CHANGING EXTENSION NAME IN CONTROL FILES" 36 | echo "----------------------------------------" 37 | for control in "${controls[@]}"; do 38 | if [[ -f "$control" ]]; then 39 | echo "$control" 40 | # extension.so 41 | sed -i "s|${extension_so}'|${new_extension_so}'|g" "$control" 42 | # extension 43 | sed -i "s|${extension_so%".so"}'|${new_extension_so%".so"}'|g" "$control" 44 | fi 45 | done 46 | } 47 | 48 | function rename_sql_files() { 49 | echo "RENAMING EXTENSION SQL FILES" 50 | echo "----------------------------" 51 | for sql_file in $(find $install_root -name '*.sql' -type f); do 52 | echo "$sql_file" 53 | # extension.so 54 | sed -i "s|/${extension_so}'|/${new_extension_so}'|g" "$sql_file" 55 | # extension 56 | sed -i "s|/${extension_so%".so"}'|/${new_extension_so}'|g" "$sql_file" 57 | done 58 | } 59 | 60 | function rename_bitcode() { 61 | echo "RENAMING BITCODE" 62 | echo "----------------" 63 | 64 | pkglibdir=$install_root$($PG_CONFIG --pkglibdir) 65 | bitcode_extension=$pkglibdir/bitcode/${extension_so%".so"} 66 | bitcode_index=$pkglibdir/bitcode/${extension_so%".so"}.index.bc 67 | 68 | if [[ -d "${bitcode_extension}" ]]; then 69 | echo "$bitcode_extension" 70 | mv "$bitcode_extension" "$pkglibdir/bitcode/${new_extension_so%".so"}" 71 | fi 72 | 73 | if [[ -f "${bitcode_index}" ]]; then 74 | echo "$bitcode_index" 75 | mv "${bitcode_index}" "$pkglibdir/bitcode/${new_extension_so%".so"}.index.bc" 76 | fi 77 | } 78 | 79 | function rename_includes() { 80 | includedir=$install_root$($PG_CONFIG --includedir-server) 81 | echo "RENAMING INCLUDES" 82 | echo "-----------------" 83 | if [[ -d "${includedir}/extension/$PGPM_EXTENSION_NAME" ]]; then 84 | echo "$includedir" 85 | versioned_dir=${includedir}/extension/$PGPM_EXTENSION_NAME--$PGPM_EXTENSION_VERSION 86 | mkdir -p "$versioned_dir" 87 | mv "${includedir}/extension/$PGPM_EXTENSION_NAME" "$versioned_dir" 88 | fi 89 | } 90 | 91 | # Make sure we don't build a default control as it belongs 92 | # to another package 93 | function handle_default_control() { 94 | if [[ -f "$default_control" ]]; then 95 | if [[ -f "$versioned_control" ]]; then 96 | # We don't need default control if versioned is present 97 | rm -f "$default_control" 98 | else 99 | # Default becomes versioned 100 | mv "$default_control" "$versioned_control" 101 | # Don't need default_version 102 | sed -i '/default_version/d' "$versioned_control" 103 | fi 104 | fi 105 | } 106 | 107 | if [[ -n "$new_extension_so" ]]; then 108 | rename_so 109 | change_name_in_controls 110 | rename_sql_files 111 | rename_bitcode 112 | rename_incluides 113 | fi 114 | 115 | handle_default_control 116 | -------------------------------------------------------------------------------- /lib/pgpm/deb/spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "digest" 4 | require "open-uri" 5 | require "erb" 6 | 7 | module Pgpm 8 | module Deb 9 | class Spec 10 | attr_reader :package, :release, :postgres_version, :postgres_distribution 11 | 12 | def initialize(package) 13 | @postgres_distribution = Pgpm::Postgres::Distribution.in_scope 14 | @package = package 15 | @package.postgres_major_version = @postgres_distribution.major_version 16 | @release = 1 17 | end 18 | 19 | def sources 20 | @package.sources 21 | end 22 | 23 | def generate(template_name, pkg_type = :versioned) 24 | fn = "#{__dir__}/templates/#{template_name}.erb" 25 | raise "No such template: #{fn}" unless File.exist?(fn) 26 | 27 | erb = ERB.new(File.read(fn)) 28 | 29 | # Uses pkg_type parameter (which is in scope) to generate 30 | # debian/* files for versionless and main packages. 31 | erb.result(binding) 32 | end 33 | 34 | def source_version 35 | v = @package.version.to_s 36 | v.match(/\Z\d+\.\d+\Z/) ? "#{v}.0" : v 37 | end 38 | 39 | def deb_pkg_name(type = :versioned) 40 | if type == :versioned 41 | "#{@package.name.gsub("_", "-")}+#{source_version}-pg#{@package.postgres_major_version}" 42 | else 43 | "#{@package.name.gsub("_", "-")}-pg#{@package.postgres_major_version}" 44 | end 45 | end 46 | 47 | def arch 48 | # https://memgraph.com/blog/ship-it-on-arm64-or-is-it-aarch64 49 | # Debian suffixes are "amd64" and "arm64". Here we translate: 50 | case Pgpm::Arch.in_scope.name 51 | when "amd64", "x86_64" 52 | "amd64" 53 | when "aarch64", "arm64" 54 | "arm64" 55 | end 56 | end 57 | 58 | def cmds_if_not_empty(cmds, else_echo) 59 | return "\techo \"#{else_echo}\"" if cmds.nil? || cmds.empty? 60 | 61 | cmds.map!(&:to_s) 62 | cmds.map! { |c| c.gsub("$", "$$") } 63 | cmds.join("\t") 64 | end 65 | end 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /lib/pgpm/deb/templates/changelog.erb: -------------------------------------------------------------------------------- 1 | <%= deb_pkg_name(pkg_type) %> (0-1) stable; urgency=medium 2 | 3 | * Version <%= pkg_type == :versioned ? 1 : source_version %> package release. 4 | 5 | -- PGPM Debian maintainer <%= Time.now.strftime('%a, %d %b %Y %H:%M:%S %z')%> 6 | -------------------------------------------------------------------------------- /lib/pgpm/deb/templates/control.erb: -------------------------------------------------------------------------------- 1 | Source: <%= deb_pkg_name(pkg_type) %> 2 | Description: <%= self.package.description %> 3 | Section: libs 4 | Priority: optional 5 | Maintainer: PGPM Debian maintainer 6 | Rules-Requires-Root: no 7 | Build-Depends: debhelper-compat (= 13), <%= self.package.build_dependencies.join(", ") %> 8 | Standards-Version: 4.6.2 9 | 10 | Package: <%= deb_pkg_name(pkg_type) %> 11 | Depends: <%= pkg_type == :versioned ? self.package.dependencies.join(", ") : deb_pkg_name(:versioned) %> 12 | Section: libdevel 13 | Architecture: <%= arch %> 14 | Description: <%= self.package.description %> 15 | -------------------------------------------------------------------------------- /lib/pgpm/deb/templates/copyright.erb: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Source: 3 | Upstream-Name: <%= self.package.name %>-<%= self.package.version.to_s %> 4 | Upstream-Contact: 5 | 6 | Files: 7 | * 8 | Copyright: 9 | <%= self.package.license %> 10 | -------------------------------------------------------------------------------- /lib/pgpm/deb/templates/files.erb: -------------------------------------------------------------------------------- 1 | <%= deb_pkg_name(pkg_type) %>_source.buildinfo libs optional 2 | -------------------------------------------------------------------------------- /lib/pgpm/deb/templates/rules.erb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | export DEB_BUILDDIR = $(CURDIR) 4 | export PGPM_BUILDROOT = $(CURDIR) 5 | export PG_CONFIG = $(shell /usr/bin/which pg_config) 6 | export PGPM_EXTENSION_NAME = "<%= self.package.extension_name %>" 7 | export PGPM_EXTENSION_VERSION = "<%= self.package.version %>" 8 | export PGPM_INSTALL_ROOT = "$(CURDIR)/debian/<%= deb_pkg_name(pkg_type) %>" 9 | 10 | <% if pkg_type == :versioned %> 11 | %: 12 | dh $@ 13 | 14 | override_dh_auto_configure: 15 | echo " --> configuring" 16 | <%= cmds_if_not_empty self.package.configure_steps, '...nothing to configure' %> 17 | 18 | override_dh_auto_build: 19 | echo " --> building" 20 | <%= cmds_if_not_empty self.package.build_steps, '...nothing to build' %> 21 | 22 | override_dh_auto_install: 23 | echo " --> installing" 24 | dh_auto_install 25 | <%= cmds_if_not_empty self.package.install_steps, '...no custom install steps' %> 26 | chmod +x "$$DEB_BUILDDIR/prepare_artifacts.sh" 27 | find $$PGPM_INSTALL_ROOT -type f | sort - | sed 's|^$$PGPM_INSTALL_ROOT||' > .pgpm_before | sort 28 | ./prepare_artifacts.sh 29 | 30 | <% else %> 31 | %: 32 | dh $@ 33 | 34 | override_dh_auto_install: 35 | dh_auto_install 36 | echo " --> INSTALL" 37 | chmod +x "$$DEB_BUILDDIR/install_default_control.sh" 38 | ./install_default_control.sh 39 | 40 | <% end %> 41 | -------------------------------------------------------------------------------- /lib/pgpm/on_demand_file.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | class OnDemandFile 5 | attr_reader :name 6 | 7 | def initialize(name, proc) 8 | @name = name 9 | @proc = proc 10 | end 11 | 12 | private 13 | 14 | def respond_to_missing?(symbol) 15 | @io ||= @proc.call 16 | @io.respond_to?(symbol) 17 | end 18 | 19 | def method_missing(name, *args) 20 | @io ||= @proc.call 21 | @io.send(name, *args) 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/pgpm/os.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "lspace" 4 | 5 | module Pgpm 6 | module OS 7 | class Base 8 | attr_reader :arch 9 | 10 | include Pgpm::Aspects::InheritanceTracker 11 | 12 | def self.name 13 | "unknown" 14 | end 15 | 16 | def name 17 | self.class.name 18 | end 19 | 20 | def self.kind 21 | "unknown" 22 | end 23 | 24 | def kind 25 | self.class.kind 26 | end 27 | 28 | def self.builder 29 | nil 30 | end 31 | 32 | def with_scope(&block) 33 | LSpace.with(pgpm_target_operating_system: self) do 34 | block.yield 35 | end 36 | end 37 | end 38 | 39 | def self.auto_detect 40 | if RUBY_PLATFORM =~ /linux$/ 41 | Pgpm::OS::Linux.auto_detect 42 | else 43 | RUBY_PLATFORM =~ /darwin/ 44 | Pgpm::OS::Darwin.auto_detect 45 | end 46 | end 47 | 48 | def self.find(name) 49 | Base.all_subclasses.find { |klass| klass.name == name }&.new 50 | end 51 | 52 | def self.in_scope 53 | LSpace[:pgpm_target_operating_system] 54 | end 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /lib/pgpm/os/darwin.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | module OS 5 | class Darwin < Pgpm::OS::Unix 6 | def self.name 7 | "darwin" 8 | end 9 | 10 | def self.auto_detect 11 | new 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/pgpm/os/debian.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rbconfig" 4 | 5 | module Pgpm 6 | module OS 7 | class Debian < Pgpm::OS::Linux 8 | def self.auto_detect 9 | # TODO: distinguish between flavors of Debian 10 | Debian12.new 11 | end 12 | 13 | def self.name 14 | "debian" 15 | end 16 | 17 | def mock_config; end 18 | end 19 | 20 | class Debian12 < Pgpm::OS::Debian 21 | def self.name 22 | "debian-12" 23 | end 24 | 25 | def self.builder 26 | Pgpm::Debian::Builder 27 | end 28 | 29 | def mock_config 30 | "debian-12-#{Pgpm::Arch.in_scope.name}+pgdg" 31 | end 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/pgpm/os/linux.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | module OS 5 | class Linux < Pgpm::OS::Unix 6 | def self.auto_detect 7 | return unless File.exist?("/etc/redhat-release") 8 | 9 | RedHat.auto_detect 10 | end 11 | 12 | def self.name 13 | "linux" 14 | end 15 | 16 | def kind 17 | "linux" 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/pgpm/os/red_hat.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rbconfig" 4 | 5 | module Pgpm 6 | module OS 7 | class RedHat < Pgpm::OS::Linux 8 | def self.auto_detect 9 | # TODO: distinguish between flavors of RedHat 10 | RockyEPEL9.new 11 | end 12 | 13 | def self.name 14 | "redhat" 15 | end 16 | 17 | def mock_config; end 18 | end 19 | 20 | class RockyEPEL9 < Pgpm::OS::RedHat 21 | def self.name 22 | "rocky+epel-9" 23 | end 24 | 25 | def self.builder 26 | Pgpm::RPM::Builder 27 | end 28 | 29 | def mock_config 30 | "rocky+epel-9-#{Pgpm::Arch.in_scope.name}+pgdg" 31 | end 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/pgpm/os/unix.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | module OS 5 | class Unix < Pgpm::OS::Base 6 | def self.name 7 | "unix" 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/pgpm/package.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "dry/inflector" 4 | 5 | module Pgpm 6 | class Package 7 | include Pgpm::Aspects::InheritanceTracker 8 | include AbstractPackage 9 | include Source 10 | include Naming 11 | include Metadata 12 | include Dependencies 13 | include Git 14 | include GitHub 15 | include PGXN 16 | include Versioning 17 | include Subscripting 18 | include Enumerating 19 | include Native 20 | include Building 21 | include Make 22 | include Rust 23 | include Initialization 24 | include Packaging 25 | include Contrib 26 | include WithPath 27 | 28 | def inspect 29 | "#<#{self.class}:#{self.class.package_name} #{version}>" 30 | end 31 | 32 | abstract_package 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/pgpm/package/abstract_package.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | class Package 5 | module AbstractPackage 6 | module ClassMethods 7 | def abstract_package? 8 | @is_abstract_package || false 9 | end 10 | 11 | protected 12 | 13 | def abstract_package 14 | @is_abstract_package = true 15 | end 16 | end 17 | 18 | def self.included(base_class) 19 | base_class.extend(ClassMethods) 20 | end 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/pgpm/package/building.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | class Package 5 | module Building 6 | def configure_steps 7 | [] 8 | end 9 | 10 | def source_url_directory_name 11 | nil 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/pgpm/package/contrib.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | class Package 5 | module Contrib 6 | def contrib? 7 | self.class.instance_variable_get(:@contrib) 8 | end 9 | 10 | module ClassMethods 11 | def contrib_package 12 | @contrib = true 13 | end 14 | 15 | def package_name(exclude_namespace: false) 16 | if contrib? 17 | super(exclude_namespace: true) 18 | else 19 | super 20 | end 21 | end 22 | 23 | def contrib? 24 | @contrib 25 | end 26 | 27 | def package_versions 28 | if contrib? 29 | Class.new do 30 | include Enumerable 31 | 32 | def include?(_version) 33 | true 34 | end 35 | 36 | def empty? 37 | false 38 | end 39 | 40 | def each 41 | yield "*" 42 | end 43 | end.new 44 | else 45 | super 46 | end 47 | end 48 | end 49 | 50 | def self.included(base_class) 51 | base_class.extend(ClassMethods) 52 | end 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /lib/pgpm/package/dependencies.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "tsort" 4 | 5 | module Pgpm 6 | class Package 7 | module Dependencies 8 | attr_accessor :postgres_major_version 9 | 10 | def build_dependencies 11 | case Pgpm::OS.in_scope.class.name 12 | when "debian", "ubuntu" 13 | deps = [ 14 | "postgresql-#{postgres_major_version}", 15 | "postgresql-server-dev-#{postgres_major_version}", 16 | "postgresql-common" 17 | ] 18 | if native? 19 | deps << "build-essential" 20 | end 21 | when "rocky+epel-9", "redhat", "fedora" 22 | [] 23 | end 24 | end 25 | 26 | def dependencies 27 | case Pgpm::OS.in_scope.class.name 28 | when "debian", "ubuntu" 29 | ["postgresql-#{postgres_major_version}"] 30 | when "rocky+epel-9", "redhat", "fedora" 31 | [] 32 | end 33 | end 34 | 35 | def requires 36 | [] 37 | end 38 | 39 | def all_requirements 40 | requires.flat_map { |r| [r, *r.all_requirements] }.uniq 41 | end 42 | 43 | def topologically_ordered_with_dependencies 44 | TopologicalPackageSorter.new([self, *all_requirements]).sorted_packages 45 | end 46 | 47 | class TopologicalPackageSorter 48 | include TSort 49 | 50 | def initialize(packages) 51 | @packages = packages.each_with_object({}) do |pkg, hash| 52 | hash[pkg.name] = pkg 53 | end 54 | end 55 | 56 | def tsort_each_node(&block) 57 | @packages.each_key(&block) 58 | end 59 | 60 | def tsort_each_child(node, &block) 61 | package = @packages[node] 62 | package.requires.each { |req| block.call(req) if @packages.key?(req) } 63 | end 64 | 65 | def sorted_packages 66 | tsort.map { |name| @packages[name] }.reverse 67 | end 68 | end 69 | 70 | def c_files_present? 71 | Dir.glob("*.c", base: source).any? 72 | end 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /lib/pgpm/package/enumerating.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | class Package 5 | module Enumerating 6 | def self.included(base_class) 7 | class << base_class 8 | include Enumerable 9 | def each(&block) 10 | if self == Pgpm::Package 11 | all_subclasses.each(&block) 12 | else 13 | package_versions.map { |v| new(v) }.each(&block) 14 | end 15 | end 16 | end 17 | end 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/pgpm/package/git.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "git" 4 | 5 | module Pgpm 6 | class Package 7 | module Git 8 | Config = Data.define(:url, :download_version_tags, :tag_prefix, :version_pattern) 9 | 10 | module ClassMethods 11 | attr_reader :git_config 12 | 13 | module Methods 14 | SEMVER = /(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/ 15 | 16 | def package_versions 17 | if !git_config.download_version_tags 18 | super 19 | else 20 | prefix_re = Regexp.quote(git_config.tag_prefix.to_s) 21 | prefix_re = git_config.tag_prefix if git_config.tag_prefix.is_a?(Regexp) 22 | git_term_prompt = ENV["GIT_TERMINAL_PROMPT"] 23 | ENV["GIT_TERMINAL_PROMPT"] = "0" 24 | begin 25 | @tags ||= 26 | ::Git.ls_remote(git_config.url)["tags"].keys 27 | .filter { |key| !key.end_with?("^{}") } 28 | .filter { |key| key.match?(/^(#{prefix_re})#{git_config.version_pattern || SEMVER}/) } 29 | rescue StandardError 30 | @tags ||= [] 31 | end 32 | ENV["GIT_TERMINAL_PROMPT"] = git_term_prompt 33 | versions = @tags.map { |tag| tag.gsub(/^(#{prefix_re})/, "") }.map { |v| Pgpm::Package::Version.new(v) } 34 | @tag_versions = Hash[@tags.zip(versions)] 35 | @version_tags = Hash[versions.zip(@tags)] 36 | versions 37 | end 38 | end 39 | end 40 | 41 | def git(url, download_version_tags: true, tag_prefix: /v?/, version_pattern: nil) 42 | @git_config = Config.new(url:, download_version_tags:, tag_prefix:, version_pattern:) 43 | extend Methods 44 | end 45 | end 46 | 47 | def version_git_tag 48 | self.class.package_versions if self.class.instance_variable_get(:@version_tags).nil? 49 | version_tags = self.class.instance_variable_get(:@version_tags) || {} 50 | version_tags[version] 51 | end 52 | 53 | def version_git_commit 54 | nil 55 | end 56 | 57 | def source 58 | directory = Pgpm::Cache.directory.join(name, version.to_s) 59 | tag = version_git_tag 60 | commit = version_git_commit 61 | directory = Pgpm::Cache.directory.join(name, commit) if commit 62 | if File.directory?(directory) && File.directory?(directory.join(".git")) 63 | directory 64 | elsif File.directory?(directory) 65 | raise "Unexpected non-git directory #{directory}" 66 | else 67 | if tag 68 | ::Git.clone(self.class.git_config.url, directory, depth: 1, branch: version_git_tag) 69 | elsif commit 70 | g = ::Git.clone(self.class.git_config.url, directory) 71 | g.checkout("checkout-#{commit}", new_branch: true, start_point: commit) 72 | else 73 | ::Git.clone(self.class.git_config.url, directory, depth: 1) 74 | end 75 | directory 76 | end 77 | end 78 | 79 | def release_date 80 | ::Git.open(source).log.first.date 81 | end 82 | 83 | def self.included(base_class) 84 | base_class.extend(ClassMethods) 85 | end 86 | end 87 | end 88 | end 89 | -------------------------------------------------------------------------------- /lib/pgpm/package/git_hub.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "open-uri" 4 | 5 | module Pgpm 6 | class Package 7 | module GitHub 8 | Config = Data.define(:name, :download_version_tags) 9 | 10 | module Methods 11 | def sources 12 | commit = version_git_tag || version_git_commit 13 | [Pgpm::OnDemandFile.new("#{version}.tar.gz", lambda { 14 | URI.open("https://github.com/#{self.class.github_config.name}/archive/#{commit}.tar.gz") 15 | })] + super 16 | end 17 | 18 | def source_url_directory_name 19 | # GitHub strips leading `v` from version tags 20 | commit = version_git_tag&.gsub(/^v/, "") || version_git_commit 21 | "#{self.class.github_config.name.split("/").last}-#{commit}" 22 | end 23 | end 24 | 25 | module ClassMethods 26 | attr_reader :github_config 27 | 28 | def github(name, download_version_tags: true, tag_prefix: /v?/, version_pattern: nil) 29 | @github_config = Config.new(name:, download_version_tags:) 30 | include Pgpm::Package::Git 31 | include Methods 32 | git "https://github.com/#{@github_config.name}", download_version_tags:, tag_prefix:, version_pattern: 33 | end 34 | end 35 | 36 | def self.included(base_class) 37 | base_class.extend(ClassMethods) 38 | end 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /lib/pgpm/package/initialization.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | class Package 5 | module Initialization 6 | def initialize(version) 7 | @version = version 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/pgpm/package/make.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | class Package 5 | module Make 6 | def build_steps 7 | [Pgpm::Commands::Make.new("PG_CONFIG=$PG_CONFIG")] if makefile_present? 8 | end 9 | 10 | def install_steps 11 | return unless makefile_present? 12 | 13 | [Pgpm::Commands::Make.new("install", "DESTDIR=$PGPM_INSTALL_ROOT", "PG_CONFIG=$PG_CONFIG")] 14 | end 15 | 16 | def makefile_present? 17 | !Dir.glob(%w[Makefile GNUmakefile makefile], base: source.to_s).empty? 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/pgpm/package/metadata.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | class Package 5 | module Metadata 6 | def summary 7 | "TODO: summary" 8 | end 9 | 10 | def description 11 | "TODO: description" 12 | end 13 | 14 | def all_searchable_texts 15 | [name, summary, description] 16 | end 17 | 18 | def license 19 | "TODO: license" 20 | end 21 | 22 | def release_date; end 23 | 24 | def broken? 25 | requires.any?(&:broken?) 26 | end 27 | 28 | module ClassMethods 29 | def extension_name 30 | self[:latest]&.extension_name 31 | end 32 | 33 | def description 34 | self[:latest]&.description 35 | end 36 | 37 | def summary 38 | self[:latest]&.summary 39 | end 40 | 41 | def license 42 | self[:latest]&.license 43 | end 44 | 45 | def release_date 46 | self[:latest]&.release_date 47 | end 48 | 49 | def all_searchable_texts 50 | self[:latest]&.all_searchable_texts || [] 51 | end 52 | end 53 | 54 | def self.included(base_class) 55 | base_class.extend(ClassMethods) 56 | end 57 | end 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /lib/pgpm/package/naming.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | class Package 5 | module Naming 6 | module ClassMethods 7 | def package_name(exclude_namespace: false) 8 | modules = to_s.split("::") 9 | class_name = modules.last 10 | name = @name || Dry::Inflector.new.underscore(class_name) 11 | if exclude_namespace 12 | name 13 | else 14 | namespace = modules[..-2].map { |m| Dry::Inflector.new.underscore(m) }.join("/") 15 | namespace += "/" unless namespace.empty? 16 | namespace + name 17 | end 18 | end 19 | 20 | protected 21 | 22 | def name(name) 23 | @name = name 24 | end 25 | end 26 | 27 | def self.included(base_class) 28 | base_class.extend(ClassMethods) 29 | end 30 | 31 | def name(exclude_namespace: true) 32 | self.class.package_name(exclude_namespace:) 33 | end 34 | 35 | def extension_name 36 | name 37 | end 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/pgpm/package/native.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | class Package 5 | module Native 6 | def native?(path = ".") 7 | Dir.glob("**/*.{c,rs,cpp,cc,zig,go,adb,s}", base: File.join(source, path)).any? 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/pgpm/package/packaging.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | class Package 5 | module Packaging 6 | def to_rpm_spec(**opts) 7 | Pgpm::RPM::Spec.new(self, **opts) 8 | end 9 | 10 | def to_deb_spec(**opts) 11 | Pgpm::Deb::Spec.new(self, **opts) 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/pgpm/package/pgxn.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "oj" 4 | 5 | module Pgpm 6 | class Package 7 | module PGXN 8 | def provides_pgxn_meta_json? 9 | File.directory?(source) && File.file?(pgxn_meta_json_path) 10 | end 11 | 12 | def pgxn_meta_json 13 | @pgxn_meta_json ||= Oj.load(File.read(pgxn_meta_json_path)) 14 | end 15 | 16 | def pgxn_meta_json_path 17 | source.join("META.json") 18 | end 19 | 20 | def extension_name 21 | if provides_pgxn_meta_json? 22 | pgxn_meta_json["name"] 23 | else 24 | super 25 | end 26 | end 27 | 28 | def summary 29 | if provides_pgxn_meta_json? 30 | pgxn_meta_json["abstract"] 31 | else 32 | super 33 | end 34 | end 35 | 36 | def description 37 | if provides_pgxn_meta_json? 38 | pgxn_meta_json["description"] 39 | else 40 | super 41 | end 42 | end 43 | 44 | def license 45 | if provides_pgxn_meta_json? 46 | lic = pgxn_meta_json["license"] 47 | case lic 48 | when Hash 49 | lic.keys.join(" or ") 50 | when Array 51 | lic.join(" or ") 52 | when String 53 | lic 54 | end 55 | else 56 | super 57 | end 58 | end 59 | 60 | def license_text 61 | path = source.to_s 62 | %w[license lisence unlicense unlisence copying].each do |fn| 63 | [fn, fn.capitalize, fn.upcase].each do |fn2| 64 | ["", ".txt", ".md"].each do |fn3| 65 | if File.exist?("#{path}/#{fn2}#{fn3}") 66 | return File.read("#{path}/#{fn2}#{fn3}") 67 | end 68 | end 69 | end 70 | end 71 | nil 72 | end 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /lib/pgpm/package/rust.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "open-uri" 4 | require "perfect_toml" 5 | 6 | module Pgpm 7 | class Package 8 | # rubocop:disable Metrics/ModuleLength 9 | module Rust 10 | ARCH_MAPPING = { "arm64" => "aarch64" }.freeze 11 | OS_MAPPING = { "linux" => "unknown-linux-gnu" }.freeze 12 | 13 | def rust_default_features 14 | [] 15 | end 16 | 17 | def sources 18 | if cargo_toml_present? 19 | return @srcs if @srcs 20 | 21 | @srcs = super 22 | 23 | vendor_dir = Dir.mktmpdir("pgpm") 24 | 25 | podman_cmd = "run -v #{Pgpm::Cache.directory}:#{Pgpm::Cache.directory} -v #{vendor_dir}:#{vendor_dir} -i rust" 26 | Podman.run("#{podman_cmd} cargo add --manifest-path #{source}/Cargo.toml --dev cargo-pgrx@#{pgrx_version}") 27 | Podman.run("#{podman_cmd} cargo vendor --versioned-dirs --manifest-path #{source}/Cargo.toml #{vendor_dir}/vendor") 28 | vendored_pgrx_version = Dir.glob("cargo-pgrx-*", base: File.join(vendor_dir, "vendor"))[0].split("-").last 29 | # Get cargo-pgrx's dependencies vendored, too 30 | Podman.run("#{podman_cmd} cargo vendor --no-delete --versioned-dirs --manifest-path #{vendor_dir}/vendor/cargo-pgrx-#{vendored_pgrx_version}/Cargo.toml #{vendor_dir}/vendor") 31 | File.write(File.join(vendor_dir, "vendor", "PGRX_VERSION"), vendored_pgrx_version) # Write it down so that configure steps don't have to guess 32 | 33 | @srcs.push(vendored_tar_gz(vendor_dir)) 34 | 35 | FileUtils.rm_rf(vendor_dir) 36 | 37 | @srcs.push(Pgpm::OnDemandFile.new("rust.tar.xz", lambda { 38 | # rubocop:disable Security/Open 39 | URI.open(channel_rust_stable[:pkg][:rust][:target][rust_target.to_sym][:xz_url]) 40 | # rubocop:enable Security/Open 41 | })) 42 | 43 | @srcs 44 | else 45 | super 46 | end 47 | end 48 | 49 | def build_dependencies 50 | if cargo_toml_present? 51 | super + [ 52 | # I currently have no hope of being able to get distros to support bleeding-edge MSRV, 53 | # so this is what we mean but for now we just package Rust with us (which makes our sources 54 | # large, sadly) 55 | # "cargo >= #{rust_minimum_version}", "rust >= #{rust_minimum_version}", 56 | # "rustfmt >= #{rust_minimum_version}", # pgrx->bindgen 57 | "openssl-devel" # pgrx needs it 58 | ] 59 | else 60 | super 61 | end 62 | end 63 | 64 | def configure_steps 65 | if cargo_toml_present? 66 | config = <<~EOF 67 | [profile.release-with-debug] 68 | inherits = "release" 69 | debug = true 70 | 71 | [source.crates-io] 72 | replace-with = "vendored-sources" 73 | 74 | [source.vendored-sources] 75 | directory = "vendor" 76 | EOF 77 | super + [ 78 | "rust-#{current_stable_rust}-#{rust_target}/install.sh --prefix=rust", 79 | "export PATH=$(pwd)/rust/bin:$PATH", 80 | "mkdir -p .cargo && echo '#{config}' >> .cargo/config.toml", "cargo install --path vendor/cargo-pgrx-$(cat vendor/PGRX_VERSION)", "cargo pgrx init --pg#{Pgpm::Postgres::Distribution.in_scope.major_version} $PG_CONFIG", "cargo generate-lockfile --offline" 81 | ] 82 | else 83 | super 84 | end 85 | end 86 | 87 | def build_steps 88 | features = ["pg#{Pgpm::Postgres::Distribution.in_scope.major_version}"] + rust_default_features 89 | if cargo_toml_present? 90 | super + [ 91 | "export PATH=$(pwd)/rust/bin:$PATH", 92 | "cargo build --profile release-with-debug --no-default-features --features #{features.join(",")}" 93 | ] 94 | else 95 | super 96 | end 97 | end 98 | 99 | def install_steps 100 | if cargo_toml_present? 101 | super + [ 102 | "export PATH=$(pwd)/rust/bin:$PATH", 103 | "PGPM_REDIRECT_TO_BUILDROOT=1 cargo pgrx install --profile release-with-debug --pg-config $(pwd)/pg_config.sh" 104 | ] 105 | else 106 | super 107 | end 108 | end 109 | 110 | private 111 | 112 | def rust_target 113 | arch = Pgpm::Arch.in_scope.name 114 | os = Pgpm::OS.in_scope.kind 115 | "#{ARCH_MAPPING[arch] || arch}-#{OS_MAPPING[os] || os}" 116 | end 117 | 118 | def cargo_toml_present? 119 | File.exist?(File.join(source, "Cargo.toml")) 120 | end 121 | 122 | def cargo_toml 123 | @cargo_toml ||= PerfectTOML.load_file(File.join(source, "Cargo.toml"), symbolize_names: true) 124 | end 125 | 126 | def pgrx_version 127 | cargo_toml[:dependencies][:pgrx] 128 | end 129 | 130 | def rust_minimum_version 131 | # pgrx has no MSRV policy, always requiring the latest 132 | current_stable_rust 133 | end 134 | 135 | def channel_rust_stable 136 | @@channel_rust_stable ||= PerfectTOML.load_file(URI.open("https://static.rust-lang.org/dist/channel-rust-stable.toml"), symbolize_names: true) 137 | end 138 | 139 | def current_stable_rust 140 | channel_rust_stable[:pkg][:rust][:version].split(" ").first 141 | end 142 | 143 | def vendored_tar_gz(dir) 144 | s = String.new 145 | begin 146 | sgz = Zlib::GzipWriter.new(StringIO.new(s)) 147 | tar = Minitar::Output.open(sgz) 148 | Find.find(dir) do |entry| 149 | stat = File.stat(entry) 150 | data = File.directory?(entry) ? nil : File.binread(entry) 151 | info = { name: Pathname(entry).relative_path_from(dir).to_s, 152 | mode: stat.mode, uid: stat.uid, gid: stat.gid, mtime: stat.mtime } 153 | Minitar.pack_as_file(info, data, tar) 154 | end 155 | ensure 156 | # Closes both tar and sgz. 157 | tar.close 158 | end 159 | Pgpm::OnDemandFile.new("vendored-sources.tar.gz", -> { StringIO.open(s) }) 160 | end 161 | 162 | # rubocop:enable Metrics/ModuleLength 163 | end 164 | end 165 | end 166 | -------------------------------------------------------------------------------- /lib/pgpm/package/source.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | class Package 5 | module Source 6 | def source 7 | raise StandardError, "no source specified" 8 | end 9 | 10 | def sources 11 | [] 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/pgpm/package/subscripting.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "semver_dialects" 4 | 5 | module Pgpm 6 | class Package 7 | module Subscripting 8 | module ClassMethods 9 | def [](name) 10 | if self == Pgpm::Package 11 | all_subclasses.find { |klass| klass.package_name == name } 12 | elsif name == :latest && package_versioning_scheme == :semver 13 | return nil if package_versions.empty? 14 | 15 | version = package_versions.map { |ver| ver.is_a?(Pgpm::Package::Version) ? ver : Pgpm::Package::Version.new(ver) }.max 16 | new(Pgpm::Package::Version.new(version.to_s)) 17 | elsif name == :latest 18 | null 19 | elsif package_versions.include?(name) 20 | new(Pgpm::Package::Version.new(name.to_s)) 21 | else 22 | all_subclasses.find { |klass| klass.package_name == name } 23 | end 24 | end 25 | end 26 | 27 | def self.included(base_class) 28 | base_class.extend(ClassMethods) 29 | end 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/pgpm/package/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "semver_dialects" 4 | 5 | module Pgpm 6 | class Package 7 | class Version 8 | include Comparable 9 | 10 | def initialize(version) 11 | recognize_version(version) 12 | @version_string = version.to_s 13 | end 14 | 15 | def to_s 16 | @version_string 17 | end 18 | 19 | def ==(other) 20 | to_s == other.to_s 21 | end 22 | 23 | alias eql? == 24 | 25 | def <=>(other) 26 | raise "unsupported version provider" unless @version.is_a?(SemverDialects::BaseVersion) 27 | 28 | @version <=> SemverDialects.parse_version(@semver_type, other.to_s) 29 | end 30 | 31 | def hash 32 | to_s.hash 33 | end 34 | 35 | def major 36 | to_s.split(".").first.to_i 37 | end 38 | 39 | def minor 40 | to_s.split(".")[1].to_i 41 | end 42 | 43 | def satisfies?(range) 44 | raise "unsupported version provider" unless @version.is_a?(SemverDialects::BaseVersion) 45 | 46 | SemverDialects.version_satisfies?(@semver_type, @version_string, range) 47 | end 48 | 49 | private 50 | 51 | def recognize_version(version) 52 | @semver_type, @version = %w[cargo deb rpm].lazy.filter_map do |type| 53 | [type, SemverDialects.parse_version(type, version)] 54 | rescue SemverDialects::InvalidVersionError 55 | nil 56 | end.first || version 57 | end 58 | end 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /lib/pgpm/package/versioning.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | class Package 5 | module Versioning 6 | module ClassMethods 7 | def package_versions 8 | warn("No versions defined for #{package_name}") 9 | [] 10 | end 11 | 12 | def package_versioning_scheme 13 | @package_versioning_scheme ||= :semver 14 | end 15 | 16 | def versioning_scheme(scheme) 17 | @package_versioning_scheme = scheme 18 | end 19 | end 20 | 21 | def self.included(base_class) 22 | base_class.extend(ClassMethods) 23 | end 24 | 25 | attr_reader :version 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/pgpm/package/with_path.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "minitar" 4 | require "find" 5 | require "zlib" 6 | 7 | module Pgpm 8 | class Package 9 | module WithPath 10 | def with_path(path) 11 | @with_path = File.absolute_path(path) 12 | self 13 | end 14 | 15 | def source_url_directory_name 16 | if @with_path 17 | File.basename(@with_path) 18 | else 19 | super 20 | end 21 | end 22 | 23 | def source 24 | if @with_path 25 | Pathname(@with_path) 26 | else 27 | super 28 | end 29 | end 30 | 31 | def sources 32 | if @with_path 33 | [source_tar_gz] 34 | else 35 | super 36 | end 37 | end 38 | 39 | private 40 | 41 | def source_tar_gz 42 | Pgpm::OnDemandFile.new("sources.tar.gz", lambda { 43 | s = String.new 44 | begin 45 | dir = source 46 | sgz = Zlib::GzipWriter.new(StringIO.new(s)) 47 | tar = Minitar::Output.open(sgz) 48 | Find.find(dir) do |entry| 49 | stat = File.stat(entry) 50 | data = File.directory?(entry) ? nil : File.binread(entry) 51 | info = { name: Pathname(entry).relative_path_from(File.dirname(source)).to_s, 52 | mode: stat.mode, uid: stat.uid, gid: stat.gid, mtime: stat.mtime } 53 | Minitar.pack_as_file(info, data, tar) 54 | end 55 | ensure 56 | # Closes both tar and sgz. 57 | tar.close 58 | end 59 | StringIO.open(s) 60 | }) 61 | end 62 | end 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /lib/pgpm/podman.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "English" 4 | require "open3" 5 | require "tty-command" 6 | 7 | module Pgpm 8 | module Podman 9 | def self.run(command, unhandled_reboot_mitigation: true, print_stdout: true) 10 | result = TTY::Command.new(printer: :null).run("podman #{command}", pty: true) do |out, err| 11 | $stderr.print(out) if print_stdout 12 | warn err if err 13 | end 14 | 15 | result.out 16 | rescue TTY::Command::ExitError => e 17 | if unhandled_reboot_mitigation && e.message =~ /Please delete/ 18 | FileUtils.rm_rf(["/run/containers/storage", "/run/libpod"]) 19 | return run(command, print_stdout:, unhandled_reboot_mitigation: false) 20 | end 21 | 22 | raise 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/pgpm/postgres/distribution.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "open-uri" 4 | require "nokogiri" 5 | require "lspace" 6 | 7 | module Pgpm 8 | module Postgres 9 | class Distribution 10 | attr_reader :version 11 | 12 | def initialize(postgres_version) 13 | @version = postgres_version 14 | end 15 | 16 | def build_time_requirement_packages 17 | raise NotImplementedError 18 | end 19 | 20 | def major_version 21 | @version.split(".").first.to_i 22 | end 23 | 24 | def minor_version 25 | @version.split(".")[1].to_i 26 | end 27 | 28 | def with_scope(&block) 29 | LSpace.with(pgpm_target_postgres: self) do 30 | block.yield 31 | end 32 | end 33 | 34 | def self.in_scope 35 | LSpace[:pgpm_target_postgres] 36 | end 37 | 38 | def self.versions 39 | return @versions if @versions 40 | 41 | versions_rss = Nokogiri::XML(URI.open("https://www.postgresql.org/versions.rss")) 42 | @versions = versions_rss.search("description").map do |ver| 43 | maj, min = ver.content.split(" ").first.split(".") 44 | if "#{maj}.#{min}" =~ /\d+\.\d+/ 45 | Pgpm::Package::Version.new("#{maj}.#{min}") 46 | end 47 | end.compact.sort.reverse.group_by(&:major).map do |(major, group)| 48 | minor_versions = group.map(&:minor) 49 | full_minor_range = (0..minor_versions.max) 50 | missing_minors = full_minor_range.to_a - minor_versions 51 | filled_versions = [] 52 | missing_minors.each do |minor| 53 | filled_versions << Pgpm::Package::Version.new("#{major}.#{minor}") 54 | end 55 | 56 | filled_versions.concat(group).reverse 57 | end.flatten.reverse 58 | end 59 | end 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /lib/pgpm/postgres/redhat_based_pgdg.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | module Postgres 5 | class RedhatBasedPgdg < Distribution 6 | def build_time_requirement_packages 7 | ["postgresql#{major_version} = #{version}", 8 | "postgresql#{major_version}-devel = #{version}", 9 | "postgresql#{major_version}-server = #{version}"] 10 | end 11 | 12 | def requirement_packages 13 | ["postgresql#{major_version} = #{version}"] 14 | end 15 | 16 | def pg_config_package 17 | "postgresql#{major_version}" 18 | end 19 | 20 | def package_for(extension) 21 | case extension 22 | when Contrib::Plpython3u 23 | "postgresql#{major_version}-plpython3 = #{version}" 24 | else 25 | "postgresql#{major_version}-contrib = #{version}" 26 | end 27 | end 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/pgpm/rpm.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "digest" 4 | require "open-uri" 5 | 6 | module Pgpm 7 | module RPM 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/pgpm/rpm/builder.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | module RPM 5 | class Builder 6 | def initialize(spec) 7 | @spec = spec 8 | end 9 | 10 | def source_builder(target_directory = nil) 11 | target_directory ||= "." 12 | dir = Dir.mktmpdir("pgpm") 13 | File.open(Pathname(dir).join("#{safe_package_name}.spec"), "w") do |specfile| 14 | specfile.write(@spec.to_s) 15 | specfile.close 16 | sources = File.join(dir, "sources") 17 | FileUtils.mkdir_p(sources) 18 | @spec.sources.map do |src| 19 | print "Downloading #{src.name}..." 20 | srcfile = File.join(sources, src.name) 21 | File.write(srcfile, src.read) 22 | puts " done." 23 | end 24 | cfg = Pgpm::RPM::Mock::Config.new(Pgpm::OS.in_scope.mock_config) 25 | Pgpm::RPM::Mock::Operation.buildsrpm(specfile.path, sources, config: cfg.path, result_dir: target_directory, cb: lambda { 26 | FileUtils.rm_rf(dir) 27 | }) 28 | end 29 | end 30 | 31 | def versionless_builder(target_directory = nil) 32 | target_directory ||= "." 33 | dir = Dir.mktmpdir("pgpm") 34 | File.open(Pathname(dir).join("#{safe_package_name}.spec"), "w") do |specfile| 35 | specfile.write(@spec.versionless) 36 | specfile.close 37 | cfg = Pgpm::RPM::Mock::Config.new(Pgpm::OS.in_scope.mock_config) 38 | Pgpm::RPM::Mock::Operation.buildsrpm(specfile.path, nil, config: cfg.path, result_dir: target_directory, cb: lambda { 39 | FileUtils.rm_rf(dir) 40 | }) 41 | end 42 | end 43 | 44 | def self.builder(srpm) 45 | target_directory ||= "." 46 | cfg = Pgpm::RPM::Mock::Config.new(Pgpm::OS.in_scope.mock_config) 47 | srpm = [srpm] if srpm.is_a?(String) 48 | srpm.reduce(nil) do |b, rpm| 49 | op = Pgpm::RPM::Mock::Operation.rebuild(rpm, config: cfg.path, result_dir: target_directory) 50 | b.nil? ? op : b.chain(op) 51 | end 52 | end 53 | 54 | private 55 | 56 | def safe_package_name 57 | @spec.package.name.gsub(%r{/}, "__") 58 | end 59 | end 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /lib/pgpm/rpm/mock/config.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | module RPM 5 | module Mock 6 | class Config 7 | def initialize(name) 8 | @source = name 9 | @path = File.absolute_path(File.join(File.dirname(__FILE__), "..", "mock", "configs", "#{name}.cfg")) 10 | end 11 | 12 | attr_reader :path 13 | end 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/pgpm/rpm/mock/configs/rocky+epel-9-aarch64+pgdg.cfg: -------------------------------------------------------------------------------- 1 | include('rocky+epel-9-aarch64.cfg') 2 | 3 | config_opts['root'] = 'rocky+epel-9-aarch64+pgdg{{pgdg_version}}' 4 | 5 | config_opts['description'] = 'Rocky Linux EPEL 9 with pgdg {{ pgdg_version }}' 6 | config_opts['dnf.conf'] += """ 7 | 8 | ######################################################### 9 | # PGDG Red Hat Enterprise Linux / Rocky repositories # 10 | ######################################################### 11 | 12 | # PGDG Red Hat Enterprise Linux / Rocky stable common repository for all PostgreSQL versions 13 | 14 | [pgdg-common] 15 | name=PostgreSQL common RPMs for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} 16 | baseurl=https://download.postgresql.org/pub/repos/yum/common/redhat/rhel-$releasever-{{target_arch}} 17 | enabled=1 18 | gpgcheck=1 19 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-AARCH64-RHEL 20 | repo_gpgcheck = 1 21 | 22 | # Red Hat recently breaks compatibility between 9.n and 9.n+1. PGDG repo is 23 | # affected with the LLVM repo. This is a band aid repo for the llvmjit users 24 | # whose installations cannot be updated. 25 | 26 | [pgdg-rocky9-sysupdates] 27 | name=PostgreSQL Supplementary ucommon RPMs for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} 28 | baseurl=https://download.postgresql.org/pub/repos/yum/common/pgdg-rocky9-sysupdates/redhat/rhel-$releasever-{{target_arch}} 29 | enabled=0 30 | gpgcheck=1 31 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-AARCH64-RHEL 32 | repo_gpgcheck = 1 33 | 34 | # We provide extra package to support some RPMs in the PostgreSQL RPM repo, like 35 | # consul, haproxy, etc. 36 | 37 | [pgdg-rhel9-extras] 38 | name=Extra packages to support some RPMs in the PostgreSQL RPM repo for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} 39 | baseurl=https://download.postgresql.org/pub/repos/yum/common/pgdg-rhel$releasever-extras/redhat/rhel-$releasever-{{target_arch}} 40 | enabled=0 41 | gpgcheck=1 42 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-AARCH64-RHEL 43 | repo_gpgcheck = 1 44 | 45 | # PGDG Red Hat Enterprise Linux / Rocky stable repositories: 46 | 47 | [pgdg{{pgdg_version}}] 48 | name=PostgreSQL {{pgdg_version}} for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} 49 | baseurl=https://download.postgresql.org/pub/repos/yum/{{pgdg_version}}/redhat/rhel-$releasever-{{target_arch}} 50 | enabled=1 51 | gpgcheck=1 52 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-AARCH64-RHEL 53 | repo_gpgcheck = 1 54 | 55 | # PGDG RHEL / Rocky / AlmaLinux Updates Testing common repositories. 56 | 57 | [pgdg-common-testing] 58 | name=PostgreSQL common testing RPMs for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} 59 | baseurl=https://download.postgresql.org/pub/repos/yum/testing/common/redhat/rhel-$releasever-{{target_arch}} 60 | enabled=0 61 | gpgcheck=1 62 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-AARCH64-RHEL 63 | repo_gpgcheck = 1 64 | 65 | # PGDG RHEL / Rocky / AlmaLinux Updates Testing repositories. (These packages should not be used in production) 66 | # Available for 12 and above. 67 | 68 | [pgdg{{pgdg_version}}-updates-testing] 69 | name=PostgreSQL {{pgdg_version}} for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} - Updates testing 70 | baseurl=https://download.postgresql.org/pub/repos/yum/testing/17/redhat/rhel-$releasever-{{target_arch}} 71 | enabled=0 72 | gpgcheck=0 73 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-AARCH64-RHEL 74 | repo_gpgcheck = 1 75 | 76 | # PGDG Red Hat Enterprise Linux / Rocky SRPM testing common repository 77 | 78 | [pgdg-source-common] 79 | name=PostgreSQL for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} - Source 80 | baseurl=https://download.postgresql.org/pub/repos/yum/srpms/common/redhat/rhel-$releasever-{{target_arch}} 81 | enabled=0 82 | gpgcheck=1 83 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-AARCH64-RHEL 84 | repo_gpgcheck = 1 85 | 86 | # PGDG RHEL / Rocky / AlmaLinux testing common SRPM repository for all PostgreSQL versions 87 | 88 | [pgdg-common-srpm-testing] 89 | name=PostgreSQL common testing SRPMs for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} 90 | baseurl=https://download.postgresql.org/pub/repos/yum/srpms/testing/common/redhat/rhel-$releasever-{{target_arch}} 91 | enabled=0 92 | gpgcheck=1 93 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-AARCH64-RHEL 94 | repo_gpgcheck = 1 95 | 96 | # PGDG Source RPMs (SRPM), and their testing repositories: 97 | 98 | [pgdg{{pgdg_version}}-source-updates-testing] 99 | name=PostgreSQL {{pgdg_version}} for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} - Source updates testing 100 | baseurl=https://download.postgresql.org/pub/repos/yum/srpms/testing/{{pgdg_version}}/redhat/rhel-$releasever-{{target_arch}} 101 | enabled=0 102 | gpgcheck=0 103 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-AARCH64-RHEL 104 | repo_gpgcheck = 1 105 | 106 | [pgdg{{pgdg_version}}-source] 107 | name=PostgreSQL {{pgdg_version}} for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} - Source 108 | baseurl=https://download.postgresql.org/pub/repos/yum/srpms/16/redhat/rhel-$releasever-{{target_arch}} 109 | enabled=0 110 | gpgcheck=1 111 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-AARCH64-RHEL 112 | repo_gpgcheck = 1 113 | 114 | # Debuginfo/debugsource packages for stable repos 115 | 116 | [pgdg{{pgdg_version}}-debuginfo] 117 | name=PostgreSQL {{pgdg_version}} for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} - Debuginfo 118 | baseurl=https://dnf-debuginfo.postgresql.org/debug/{{pgdg_version}}/redhat/rhel-$releasever-{{target_arch}} 119 | enabled=0 120 | gpgcheck=1 121 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-AARCH64-RHEL 122 | repo_gpgcheck = 1 123 | 124 | [pgdg{{pgdg_version}}-updates-testing-debuginfo] 125 | name=PostgreSQL {{pgdg_version}} for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} - Debuginfo 126 | baseurl=https://dnf-debuginfo.postgresql.org/testing/debug/{{pgdg_version}}/redhat/rhel-$releasever-{{target_arch}} 127 | enabled=0 128 | gpgcheck=0 129 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-AARCH64-RHEL 130 | repo_gpgcheck = 1 131 | """ -------------------------------------------------------------------------------- /lib/pgpm/rpm/mock/configs/rocky+epel-9-x86_64+pgdg.cfg: -------------------------------------------------------------------------------- 1 | include('rocky+epel-9-x86_64.cfg') 2 | 3 | config_opts['root'] = 'rocky+epel-9-x86_64+pgdg{{pgdg_version}}' 4 | 5 | config_opts['description'] = 'Rocky Linux EPEL 9 with pgdg {{ pgdg_version }}' 6 | config_opts['dnf.conf'] += """ 7 | 8 | ######################################################### 9 | # PGDG Red Hat Enterprise Linux / Rocky repositories # 10 | ######################################################### 11 | 12 | # PGDG Red Hat Enterprise Linux / Rocky stable common repository for all PostgreSQL versions 13 | 14 | [pgdg-common] 15 | name=PostgreSQL common RPMs for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} 16 | baseurl=https://download.postgresql.org/pub/repos/yum/common/redhat/rhel-$releasever-{{target_arch}} 17 | enabled=1 18 | gpgcheck=1 19 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL 20 | repo_gpgcheck = 1 21 | 22 | # Red Hat recently breaks compatibility between 9.n and 9.n+1. PGDG repo is 23 | # affected with the LLVM repo. This is a band aid repo for the llvmjit users 24 | # whose installations cannot be updated. 25 | 26 | [pgdg-rocky9-sysupdates] 27 | name=PostgreSQL Supplementary ucommon RPMs for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} 28 | baseurl=https://download.postgresql.org/pub/repos/yum/common/pgdg-rocky9-sysupdates/redhat/rhel-$releasever-{{target_arch}} 29 | enabled=0 30 | gpgcheck=1 31 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL 32 | repo_gpgcheck = 1 33 | 34 | # We provide extra package to support some RPMs in the PostgreSQL RPM repo, like 35 | # consul, haproxy, etc. 36 | 37 | [pgdg-rhel9-extras] 38 | name=Extra packages to support some RPMs in the PostgreSQL RPM repo for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} 39 | baseurl=https://download.postgresql.org/pub/repos/yum/common/pgdg-rhel$releasever-extras/redhat/rhel-$releasever-{{target_arch}} 40 | enabled=0 41 | gpgcheck=1 42 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL 43 | repo_gpgcheck = 1 44 | 45 | # PGDG Red Hat Enterprise Linux / Rocky stable repositories: 46 | 47 | [pgdg{{pgdg_version}}] 48 | name=PostgreSQL {{pgdg_version}} for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} 49 | baseurl=https://download.postgresql.org/pub/repos/yum/{{pgdg_version}}/redhat/rhel-$releasever-{{target_arch}} 50 | enabled=1 51 | gpgcheck=1 52 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL 53 | repo_gpgcheck = 1 54 | 55 | # PGDG RHEL / Rocky / AlmaLinux Updates Testing common repositories. 56 | 57 | [pgdg-common-testing] 58 | name=PostgreSQL common testing RPMs for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} 59 | baseurl=https://download.postgresql.org/pub/repos/yum/testing/common/redhat/rhel-$releasever-{{target_arch}} 60 | enabled=0 61 | gpgcheck=1 62 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL 63 | repo_gpgcheck = 1 64 | 65 | # PGDG RHEL / Rocky / AlmaLinux Updates Testing repositories. (These packages should not be used in production) 66 | # Available for 12 and above. 67 | 68 | [pgdg{{pgdg_version}}-updates-testing] 69 | name=PostgreSQL {{pgdg_version}} for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} - Updates testing 70 | baseurl=https://download.postgresql.org/pub/repos/yum/testing/17/redhat/rhel-$releasever-{{target_arch}} 71 | enabled=0 72 | gpgcheck=0 73 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL 74 | repo_gpgcheck = 1 75 | 76 | # PGDG Red Hat Enterprise Linux / Rocky SRPM testing common repository 77 | 78 | [pgdg-source-common] 79 | name=PostgreSQL for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} - Source 80 | baseurl=https://download.postgresql.org/pub/repos/yum/srpms/common/redhat/rhel-$releasever-{{target_arch}} 81 | enabled=0 82 | gpgcheck=1 83 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL 84 | repo_gpgcheck = 1 85 | 86 | # PGDG RHEL / Rocky / AlmaLinux testing common SRPM repository for all PostgreSQL versions 87 | 88 | [pgdg-common-srpm-testing] 89 | name=PostgreSQL common testing SRPMs for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} 90 | baseurl=https://download.postgresql.org/pub/repos/yum/srpms/testing/common/redhat/rhel-$releasever-{{target_arch}} 91 | enabled=0 92 | gpgcheck=1 93 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL 94 | repo_gpgcheck = 1 95 | 96 | # PGDG Source RPMs (SRPM), and their testing repositories: 97 | 98 | [pgdg{{pgdg_version}}-source-updates-testing] 99 | name=PostgreSQL {{pgdg_version}} for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} - Source updates testing 100 | baseurl=https://download.postgresql.org/pub/repos/yum/srpms/testing/{{pgdg_version}}/redhat/rhel-$releasever-{{target_arch}} 101 | enabled=0 102 | gpgcheck=0 103 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL 104 | repo_gpgcheck = 1 105 | 106 | [pgdg{{pgdg_version}}-source] 107 | name=PostgreSQL {{pgdg_version}} for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} - Source 108 | baseurl=https://download.postgresql.org/pub/repos/yum/srpms/16/redhat/rhel-$releasever-{{target_arch}} 109 | enabled=0 110 | gpgcheck=1 111 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL 112 | repo_gpgcheck = 1 113 | 114 | # Debuginfo/debugsource packages for stable repos 115 | 116 | [pgdg{{pgdg_version}}-debuginfo] 117 | name=PostgreSQL {{pgdg_version}} for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} - Debuginfo 118 | baseurl=https://dnf-debuginfo.postgresql.org/debug/{{pgdg_version}}/redhat/rhel-$releasever-{{target_arch}} 119 | enabled=0 120 | gpgcheck=1 121 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL 122 | repo_gpgcheck = 1 123 | 124 | [pgdg{{pgdg_version}}-updates-testing-debuginfo] 125 | name=PostgreSQL {{pgdg_version}} for RHEL / Rocky / AlmaLinux $releasever - {{target_arch}} - Debuginfo 126 | baseurl=https://dnf-debuginfo.postgresql.org/testing/debug/{{pgdg_version}}/redhat/rhel-$releasever-{{target_arch}} 127 | enabled=0 128 | gpgcheck=0 129 | gpgkey=https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL 130 | repo_gpgcheck = 1 131 | """ -------------------------------------------------------------------------------- /lib/pgpm/rpm/mock/operation.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | module RPM 5 | module Mock 6 | class Operation 7 | def self.buildsrpm(spec, sources, config: nil, result_dir: nil, cb: nil) 8 | buffer_result_dir = Dir.mktmpdir("pgpm") 9 | args = [ 10 | "--buildsrpm", "--spec", spec, "--resultdir", 11 | buffer_result_dir 12 | ] 13 | args.push("--sources", sources) if sources 14 | args.push("-r", config.to_s) unless config.nil? 15 | paths = [buffer_result_dir] 16 | paths.push(File.dirname(spec)) 17 | paths.push(File.dirname(sources)) if sources 18 | new(*args, paths:, cb: lambda { 19 | rpms = Dir.glob("*.rpm", base: buffer_result_dir).map do |f| 20 | FileUtils.cp(Pathname(buffer_result_dir).join(f), result_dir) unless result_dir.nil? 21 | File.join(File.absolute_path(result_dir), f) 22 | end 23 | FileUtils.rm_rf(buffer_result_dir) 24 | cb.call unless cb.nil? 25 | rpms 26 | }) 27 | end 28 | 29 | def self.rebuild(srpm, config: nil, result_dir: nil, cb: nil) 30 | buffer_result_dir = Dir.mktmpdir("pgpm") 31 | args = [ 32 | "--rebuild", "--chain", "--recurse", srpm, "--localrepo", buffer_result_dir 33 | ] 34 | args.push("-r", config.to_s) unless config.nil? 35 | paths = [buffer_result_dir] 36 | paths.push(File.dirname(srpm)) 37 | new(*args, paths:, cb: lambda { 38 | # Here we glob for **/*.rpm as ``--localrepo` behaves differently from 39 | # `--resultdir` 40 | rpms = Dir.glob("**/*.rpm", base: buffer_result_dir).map do |f| 41 | FileUtils.cp(Pathname(buffer_result_dir).join(f), result_dir) unless result_dir.nil? 42 | File.join(File.absolute_path(result_dir), f) 43 | end 44 | FileUtils.rm_rf(buffer_result_dir) 45 | cb.call unless cb.nil? 46 | rpms 47 | }) 48 | end 49 | 50 | def initialize(*args, opts: nil, paths: [], cb: nil) 51 | @args = args 52 | @cb = cb 53 | @paths = paths 54 | @opts = opts || { "print_main_output" => "True", "pgdg_version" => Postgres::Distribution.in_scope.major_version } 55 | end 56 | 57 | attr_reader :args, :cb 58 | 59 | def call 60 | options = @opts.flat_map { |(k, v)| ["--config-opts", "#{k}=#{v}"] }.compact.join(" ") 61 | command = "mock #{options} #{@args.join(" ")}" 62 | map_paths = @paths.map { |p| "-v #{p}:#{p}" }.join(" ") 63 | raise "Failed to execute `#{command}`" unless Podman.run("run -v #{Dir.pwd}:#{Dir.pwd} #{map_paths} --privileged -i ghcr.io/postgres-pm/pgpm #{command}") 64 | 65 | @cb&.call 66 | end 67 | 68 | def chain(op) 69 | raise ArgumentError, "can't chain non-rebuild operations" unless op.args.include?("--rebuild") && @args.include?("--rebuild") 70 | 71 | args.insert(args.index("--localrepo"), *op.args[op.args.index("--recurse") + 1..op.args.index("--localrepo") - 1]) 72 | self 73 | end 74 | 75 | def and_then(op) 76 | lambda do 77 | res1 = call 78 | res2 = op.call 79 | if res1.is_a?(Array) && res2.is_a?(Array) 80 | res1 + res2 81 | else 82 | [res1, res2] 83 | end 84 | end 85 | end 86 | end 87 | end 88 | end 89 | end 90 | -------------------------------------------------------------------------------- /lib/pgpm/rpm/scripts/pg_config.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | # Ensure PG_CONFIG is set 4 | if [[ -z "$PG_CONFIG" ]]; then 5 | echo "Error: PG_CONFIG is not set." 6 | exit 1 7 | fi 8 | 9 | # Wrapper function for pg_config 10 | pg_config_wrapper() { 11 | "$PG_CONFIG" "$@" | while read -r line; do 12 | if [[ -n "$PGPM_REDIRECT_TO_BUILDROOT" && -f "$line" || -d "$line" ]]; then 13 | echo "$PGPM_INSTALL_ROOT$line" 14 | else 15 | echo "$line" 16 | fi 17 | done 18 | } 19 | 20 | # Call the wrapper function with the arguments passed to the script 21 | pg_config_wrapper "$@" 22 | -------------------------------------------------------------------------------- /lib/pgpm/rpm/scripts/prepare_artifacts.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | set -xe 4 | 5 | new_extension_so= 6 | 7 | for file in $(find $PGPM_INSTALL_ROOT -name '*.so'); do 8 | filename=$(basename "$file") 9 | if [[ "$filename" == "${PGPM_EXTENSION_NAME}.so" ]]; then 10 | extension_so=$filename 11 | dir=$(dirname "$file") 12 | extension_dirname=${dir#"$PGPM_INSTALL_ROOT"} 13 | new_extension_so=$PGPM_EXTENSION_NAME--$PGPM_EXTENSION_VERSION.so 14 | fi 15 | done 16 | 17 | extdir=$PGPM_INSTALL_ROOT$($PG_CONFIG --sharedir)/extension 18 | 19 | # control files 20 | default_control=$extdir/$PGPM_EXTENSION_NAME.control 21 | versioned_control=$extdir/$PGPM_EXTENSION_NAME--$PGPM_EXTENSION_VERSION.control 22 | controls=("$default_control" "$versioned_control") 23 | 24 | 25 | if [[ -n "$new_extension_so" ]]; then 26 | 27 | mv "$PGPM_INSTALL_ROOT$extension_dirname/$extension_so" "$PGPM_INSTALL_ROOT$extension_dirname/$new_extension_so" 28 | 29 | # Change the extension name in controls 30 | for control in "${controls[@]}"; do 31 | if [[ -f "$control" ]]; then 32 | # extension.so 33 | sed -i "s|${extension_so}'|${new_extension_so}'|g" "$control" 34 | # extension 35 | sed -i "s|${extension_so%".so"}'|${new_extension_so%".so"}'|g" "$control" 36 | fi 37 | done 38 | 39 | # sql files 40 | for sql_file in $(find $PGPM_INSTALL_ROOT -name '*.sql' -type f); do 41 | # extension.so 42 | sed -i "s|/${extension_so}'|/${new_extension_so}'|g" "$sql_file" 43 | # extension 44 | sed -i "s|/${extension_so%".so"}'|/${new_extension_so}'|g" "$sql_file" 45 | done 46 | 47 | # bitcode 48 | 49 | pkglibdir=$PGPM_INSTALL_ROOT$($PG_CONFIG --pkglibdir) 50 | 51 | bitcode_extension=$pkglibdir/bitcode/${extension_so%".so"} 52 | bitcode_index=$pkglibdir/bitcode/${extension_so%".so"}.index.bc 53 | 54 | if [[ -d "${bitcode_extension}" ]]; then 55 | mv "${bitcode_extension}" "$pkglibdir/bitcode/${new_extension_so%".so"}" 56 | fi 57 | 58 | if [[ -f "${bitcode_index}" ]]; then 59 | mv "${bitcode_index}" "$pkglibdir/bitcode/${new_extension_so%".so"}.index.bc" 60 | fi 61 | 62 | # includes 63 | includedir=$PGPM_INSTALL_ROOT$($PG_CONFIG --includedir-server) 64 | 65 | if [[ -d "${includedir}/extension/$PGPM_EXTENSION_NAME" ]]; then 66 | versioned_dir=${includedir}/extension/$PGPM_EXTENSION_NAME--$PGPM_EXTENSION_VERSION 67 | mkdir -p "$versioned_dir" 68 | mv "${includedir}/extension/$PGPM_EXTENSION_NAME" "$versioned_dir" 69 | fi 70 | 71 | # TODO: share, docs, etc. 72 | 73 | fi 74 | 75 | 76 | # Make sure we don't build a default control as it belongs 77 | # to another package 78 | if [[ -f "$default_control" ]]; then 79 | if [[ -f "$versioned_control" ]]; then 80 | # We don't need default control if versioned is present 81 | rm -f "$default_control" 82 | else 83 | # Default becomes versioned 84 | mv "$default_control" "$versioned_control" 85 | # Don't need default_version 86 | sed -i '/default_version/d' "$versioned_control" 87 | fi 88 | fi 89 | -------------------------------------------------------------------------------- /lib/pgpm/rpm/spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "digest" 4 | require "open-uri" 5 | 6 | module Pgpm 7 | module RPM 8 | class Spec 9 | attr_reader :package, :release, :postgres_version, :postgres_distribution 10 | 11 | def initialize(package) 12 | @postgres_distribution = Pgpm::Postgres::Distribution.in_scope 13 | @package = package 14 | @release = 1 15 | 16 | # Needed in order to return correct dependencies for the selected 17 | # version of postgres and selected OS. 18 | @package.postgres_major_version = @postgres_distribution.major_version 19 | end 20 | 21 | def versionless 22 | <<~EOF 23 | Name: pgpm-#{@package.name}-#{@postgres_distribution.version} 24 | Version: #{@package.version} 25 | Release: #{@release}%{?dist} 26 | Summary: #{@package.summary} 27 | License: #{@package.license} 28 | 29 | BuildRequires: #{@postgres_distribution.build_time_requirement_packages.join(" ")} 30 | Requires: pgpm-#{@package.name}+#{@package.version}-#{@postgres_distribution.version} 31 | BuildRequires: pgpm-#{@package.name}+#{@package.version}-#{@postgres_distribution.version} 32 | BuildArch: noarch 33 | 34 | %description 35 | #{@package.description} 36 | 37 | %build 38 | 39 | %install 40 | export PG_CONFIG=$(rpm -ql #{@postgres_distribution.pg_config_package} | grep 'pg_config$') 41 | mkdir -p %{buildroot}$($PG_CONFIG --sharedir)/extension 42 | export CONTROL=%{buildroot}$($PG_CONFIG --sharedir)/extension/#{@package.extension_name}.control 43 | cat $($PG_CONFIG --sharedir)/extension/#{@package.extension_name}--#{@package.version}.control > $CONTROL 44 | echo >> $CONTROL 45 | echo "default_version = '#{@package.version}'" >> $CONTROL 46 | echo ${CONTROL#"%{buildroot}"} > filelist.txt 47 | 48 | %files -f filelist.txt 49 | EOF 50 | end 51 | 52 | def sources 53 | sources = @package.sources.clone 54 | sources.push(Pgpm::OnDemandFile.new("prepare_artifacts.sh", -> { File.open(File.join(File.dirname(__FILE__), "scripts", "prepare_artifacts.sh")) })) 55 | sources.push(Pgpm::OnDemandFile.new("pg_config.sh", -> { File.open(File.join(File.dirname(__FILE__), "scripts", "pg_config.sh")) })) 56 | sources 57 | end 58 | 59 | def to_s 60 | setup_opts = ["-q"] 61 | if @package.source_url_directory_name 62 | setup_opts.push("-n", @package.source_url_directory_name) 63 | else 64 | setup_opts.push("-n", "#{@package.name}-#{@package.version}") 65 | end 66 | 67 | <<~EOF 68 | Name: pgpm-#{@package.name}+#{@package.version}-#{@postgres_distribution.version} 69 | Version: 1 70 | Release: 1%{?dist} 71 | Summary: #{@package.summary} 72 | License: #{@package.license} 73 | #{sources.each_with_index.map { |src, index| "Source#{index}: #{src.name}" }.join("\n")} 74 | 75 | BuildRequires: #{@postgres_distribution.build_time_requirement_packages.join(" ")} 76 | #{@package.build_dependencies.uniq.map { |dep| "BuildRequires: #{dep}" }.join("\n")} 77 | #{@package.dependencies.uniq.map { |dep| "Requires: #{dep}" }.join("\n")} 78 | #{@package.requires.uniq.map do |dep| 79 | req = dep.contrib? ? @postgres_distribution.package_for(dep) : "pgpm-#{dep.name}+#{dep.version}-#{@postgres_distribution.version}" 80 | raise "Can't build with a broken dependency #{dep.name}@#{dep.version}" if dep.broken? 81 | 82 | "Requires: #{req}#{"\nBuildRequires: #{req}" if dep.contrib?}" 83 | end.join("\n") 84 | } 85 | Requires: #{@postgres_distribution.requirement_packages.join(" ")} 86 | #{"BuildArch: noarch" unless @package.native?} 87 | 88 | %description 89 | #{@package.description} 90 | 91 | %prep 92 | %setup #{setup_opts.join(" ")} 93 | #{(sources[1..] || []).filter { |s| unpack?(s) }.each_with_index.map { |_src, index| "%setup -T -D #{setup_opts.join(" ")} -a #{index + 1}" }.join("\n")} 94 | 95 | export PG_CONFIG=$(rpm -ql #{@postgres_distribution.pg_config_package} | grep 'pg_config$') 96 | #{@package.configure_steps.map(&:to_s).join("\n")} 97 | 98 | %build 99 | export PG_CONFIG=$(rpm -ql #{@postgres_distribution.pg_config_package} | grep 'pg_config$') 100 | export PGPM_INSTALL_ROOT=%{buildroot} 101 | #{@package.build_steps.map(&:to_s).join("\n")} 102 | 103 | %install 104 | export PG_CONFIG=$(rpm -ql #{@postgres_distribution.pg_config_package} | grep 'pg_config$') 105 | export PGPM_INSTALL_ROOT=%{buildroot} 106 | cp %{SOURCE#{sources.find_index { |src| src.name == "pg_config.sh" }}} ./pg_config.sh 107 | chmod +x ./pg_config.sh 108 | find %{buildroot} -type f | sort - | sed 's|^%{buildroot}||' > .pgpm_before | sort 109 | #{@package.install_steps.map(&:to_s).join("\n")} 110 | export PGPM_EXTENSION_NAME="#{@package.extension_name}" 111 | export PGPM_EXTENSION_VERSION="#{@package.version}" 112 | cp %{SOURCE#{sources.find_index { |src| src.name == "prepare_artifacts.sh" }}} ./prepare_artifacts.sh 113 | chmod +x ./prepare_artifacts.sh 114 | ./prepare_artifacts.sh 115 | find %{buildroot} -type f | sort - | sed 's|^%{buildroot}||' > .pgpm_after | sort 116 | comm -13 .pgpm_before .pgpm_after | sort -u > filelist.txt 117 | 118 | %files -f filelist.txt 119 | 120 | 121 | %changelog 122 | EOF 123 | end 124 | 125 | private 126 | 127 | def unpack?(src) 128 | src = src.name if src.respond_to?(:name) 129 | src.to_s.end_with?(".tar.gz") || src.to_s.end_with?(".tar.xz") 130 | end 131 | end 132 | end 133 | end 134 | -------------------------------------------------------------------------------- /lib/pgpm/scoped_object.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "delegate" 4 | 5 | module Pgpm 6 | class ScopedObject < SimpleDelegator 7 | def initialize(obj, *scopes) 8 | @scopes = scopes 9 | super(obj) 10 | end 11 | 12 | def method_missing(method, *args, &block) 13 | __scoped_execution(@scopes.clone, method, *args, &block) 14 | end 15 | 16 | def respond_to_missing?(m, include_private) 17 | __getobj__.respond_to_missing?(m, include_private) 18 | end 19 | 20 | private 21 | 22 | def __scoped_execution(scopes, method, *args, &block) 23 | if scopes.empty? 24 | __getobj__.send(method, *args, &block) 25 | else 26 | scope = scopes.pop 27 | scope.with_scope { __scoped_execution(scopes, method, *args, &block) } 28 | end 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /lib/pgpm/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Pgpm 4 | VERSION = "0.1.0" 5 | end 6 | -------------------------------------------------------------------------------- /packages/acl.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Acl < Pgpm::Package 4 | github "arkhipov/acl" 5 | end 6 | -------------------------------------------------------------------------------- /packages/age.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Age < Pgpm::Package 4 | github "apache/age" 5 | end 6 | -------------------------------------------------------------------------------- /packages/aggs_for_arrays.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AggsForArrays < Pgpm::Package 4 | github "pjungwir/aggs_for_arrays" 5 | end 6 | -------------------------------------------------------------------------------- /packages/aggs_for_vecs.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AggsForVecs < Pgpm::Package 4 | github "pjungwir/aggs_for_vecs" 5 | end 6 | -------------------------------------------------------------------------------- /packages/anon.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Anon < Pgpm::Package 4 | git "https://gitlab.com/dalibo/postgresql_anonymizer/" 5 | end 6 | -------------------------------------------------------------------------------- /packages/arraymath.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Arraymath < Pgpm::Package 4 | github "pramsey/pgsql-arraymath" 5 | end 6 | -------------------------------------------------------------------------------- /packages/asn1oid.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Asn1oid < Pgpm::Package 4 | github "df7cb/pgsql-asn1oid" 5 | end 6 | -------------------------------------------------------------------------------- /packages/aws_s3.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AwsS3 < Pgpm::Package 4 | github "chimpler/postgres-aws-s3" 5 | end 6 | -------------------------------------------------------------------------------- /packages/base36.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Base36 < Pgpm::Package 4 | github "adjust/pg-base36" 5 | end 6 | -------------------------------------------------------------------------------- /packages/base62.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Base62 < Pgpm::Package 4 | github "adjust/pg-base62" 5 | end 6 | -------------------------------------------------------------------------------- /packages/bgw_replstatus.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class BgwReplstatus < Pgpm::Package 4 | github "mhagander/bgw_replstatus" 5 | end 6 | -------------------------------------------------------------------------------- /packages/chkpass.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Chkpass < Pgpm::Package 4 | github "lacanoid/chkpass" 5 | end 6 | -------------------------------------------------------------------------------- /packages/citus.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Citus < Pgpm::Package 4 | github "citusdata/citus" 5 | 6 | def build_steps 7 | ["./configure"] + super 8 | end 9 | 10 | def build_dependencies 11 | super + %w[libcurl-devel lz4-devel libzstd-devel openssl-devel krb5-devel] 12 | end 13 | 14 | def dependencies 15 | super + %w[libcurl lz4 libzstd openssl krb5-libs] 16 | end 17 | 18 | def broken? 19 | # https://github.com/citusdata/citus/issues/7708 20 | version < 13 && Pgpm::Postgres::Distribution.in_scope.major_version > 16 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /packages/citus_columnar.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class CitusColumnar < Pgpm::Package 4 | github "citusdata/citus" 5 | end 6 | -------------------------------------------------------------------------------- /packages/columnar.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Columnar < Pgpm::Package 4 | github "hydradatabase/hydra" 5 | end 6 | -------------------------------------------------------------------------------- /packages/count_distinct.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class CountDistinct < Pgpm::Package 4 | github "tvondra/count_distinct" 5 | end 6 | -------------------------------------------------------------------------------- /packages/country.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Country < Pgpm::Package 4 | github "adjust/pg-country" 5 | end 6 | -------------------------------------------------------------------------------- /packages/credcheck.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Credcheck < Pgpm::Package 4 | github "MigOpsRepos/credcheck" 5 | end 6 | -------------------------------------------------------------------------------- /packages/cryptint.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Cryptint < Pgpm::Package 4 | github "dverite/cryptint" 5 | end 6 | -------------------------------------------------------------------------------- /packages/currency.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Currency < Pgpm::Package 4 | github "adjust/pg-currency" 5 | end 6 | -------------------------------------------------------------------------------- /packages/data_historization.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class DataHistorization < Pgpm::Package 4 | github "rodo/postgresql-data-historization" 5 | end 6 | -------------------------------------------------------------------------------- /packages/db2_fdw.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Db2Fdw < Pgpm::Package 4 | github "wolfgangbrandl/db2_fdw" 5 | end 6 | -------------------------------------------------------------------------------- /packages/dbt2.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Dbt2 < Pgpm::Package 4 | github "nuodb/dbt2" 5 | end 6 | -------------------------------------------------------------------------------- /packages/ddl_historization.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class DdlHistorization < Pgpm::Package 4 | github "rodo/pg_ddl_historization" 5 | end 6 | -------------------------------------------------------------------------------- /packages/ddlx.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Ddlx < Pgpm::Package 4 | github "lacanoid/pgddl", tag_prefix: "", version_pattern: /(0|[1-9]\d*)\.(0|[1-9]\d*)/ 5 | end 6 | -------------------------------------------------------------------------------- /packages/ddsketch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Ddsketch < Pgpm::Package 4 | github "tvondra/ddsketch" 5 | end 6 | -------------------------------------------------------------------------------- /packages/debversion.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Debversion < Pgpm::Package 4 | github "ATIX-AG/postgresql-debversion-evr" 5 | end 6 | -------------------------------------------------------------------------------- /packages/decoder_raw.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class DecoderRaw < Pgpm::Package 4 | github "michaelpq/pg_plugins" 5 | end 6 | -------------------------------------------------------------------------------- /packages/decoderbufs.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Decoderbufs < Pgpm::Package 4 | github "debezium/postgres-decoderbufs" 5 | end 6 | -------------------------------------------------------------------------------- /packages/duckdb_fdw.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class DuckdbFdw < Pgpm::Package 4 | github "alitrack/duckdb_fdw" 5 | end 6 | -------------------------------------------------------------------------------- /packages/emaj.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Emaj < Pgpm::Package 4 | github "dalibo/emaj" 5 | end 6 | -------------------------------------------------------------------------------- /packages/envvar.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Envvar < Pgpm::Package 4 | github "theory/pg-envvar" 5 | end 6 | -------------------------------------------------------------------------------- /packages/explain_ui.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ExplainUi < Pgpm::Package 4 | github "davidgomes/pg-explain-ui" 5 | end 6 | -------------------------------------------------------------------------------- /packages/extra_window_functions.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ExtraWindowFunctions < Pgpm::Package 4 | github "xocolatl/extra_window_functions" 5 | end 6 | -------------------------------------------------------------------------------- /packages/faker.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Faker < Pgpm::Package 4 | github "anpandu/postgresql_faker" 5 | end 6 | -------------------------------------------------------------------------------- /packages/financial.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Financial < Pgpm::Package 4 | github "intgr/pg_financial" 5 | end 6 | -------------------------------------------------------------------------------- /packages/firebird_fdw.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class FirebirdFdw < Pgpm::Package 4 | github "ibarwick/firebird_fdw" 5 | end 6 | -------------------------------------------------------------------------------- /packages/first_last_agg.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class FirstLastAgg < Pgpm::Package 4 | github "wulczer/first_last_agg" 5 | end 6 | -------------------------------------------------------------------------------- /packages/floatfile.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Floatfile < Pgpm::Package 4 | github "pjungwir/floatfile" 5 | end 6 | -------------------------------------------------------------------------------- /packages/floatvec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Floatvec < Pgpm::Package 4 | github "pjungwir/floatvec" 5 | end 6 | -------------------------------------------------------------------------------- /packages/geoip.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Geoip < Pgpm::Package 4 | github "tvondra/geoip" 5 | end 6 | -------------------------------------------------------------------------------- /packages/gzip.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Gzip < Pgpm::Package 4 | github "pramsey/pgsql-gzip" 5 | end 6 | -------------------------------------------------------------------------------- /packages/h3.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class H3 < Pgpm::Package 4 | github "zachasme/h3-pg" 5 | end 6 | -------------------------------------------------------------------------------- /packages/h3_postgis.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class H3Postgis < Pgpm::Package 4 | github "zachasme/h3-pg" 5 | end 6 | -------------------------------------------------------------------------------- /packages/hdfs_fdw.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class HdfsFdw < Pgpm::Package 4 | github "EnterpriseDB/hdfs_fdw" 5 | end 6 | -------------------------------------------------------------------------------- /packages/hll.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Hll < Pgpm::Package 4 | github "citusdata/postgresql-hll" 5 | end 6 | -------------------------------------------------------------------------------- /packages/hstore_pllua.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class HstorePllua < Pgpm::Package 4 | github "pllua/pllua" 5 | end 6 | -------------------------------------------------------------------------------- /packages/hstore_plluau.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class HstorePlluau < Pgpm::Package 4 | github "pllua/pllua" 5 | end 6 | -------------------------------------------------------------------------------- /packages/http.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Http < Pgpm::Package 4 | github "pramsey/pgsql-http" 5 | end 6 | -------------------------------------------------------------------------------- /packages/hunspell_cs_cz.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class HunspellCsCz < Pgpm::Package 4 | github "postgrespro/hunspell_dicts" 5 | end 6 | -------------------------------------------------------------------------------- /packages/hunspell_de_de.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class HunspellDeDe < Pgpm::Package 4 | github "postgrespro/hunspell_dicts" 5 | end 6 | -------------------------------------------------------------------------------- /packages/hunspell_en_us.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class HunspellEnUs < Pgpm::Package 4 | github "postgrespro/hunspell_dicts" 5 | end 6 | -------------------------------------------------------------------------------- /packages/hunspell_fr.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class HunspellFr < Pgpm::Package 4 | github "postgrespro/hunspell_dicts" 5 | end 6 | -------------------------------------------------------------------------------- /packages/hunspell_ne_np.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class HunspellNeNp < Pgpm::Package 4 | github "postgrespro/hunspell_dicts" 5 | end 6 | -------------------------------------------------------------------------------- /packages/hunspell_nl_nl.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class HunspellNlNl < Pgpm::Package 4 | github "postgrespro/hunspell_dicts" 5 | end 6 | -------------------------------------------------------------------------------- /packages/hunspell_nn_no.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class HunspellNnNo < Pgpm::Package 4 | github "postgrespro/hunspell_dicts" 5 | end 6 | -------------------------------------------------------------------------------- /packages/hunspell_pt_pt.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class HunspellPtPt < Pgpm::Package 4 | github "postgrespro/hunspell_dicts" 5 | end 6 | -------------------------------------------------------------------------------- /packages/hunspell_ru_ru.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class HunspellRuRu < Pgpm::Package 4 | github "postgrespro/hunspell_dicts" 5 | end 6 | -------------------------------------------------------------------------------- /packages/hunspell_ru_ru_aot.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class HunspellRuRuAot < Pgpm::Package 4 | github "postgrespro/hunspell_dicts" 5 | end 6 | -------------------------------------------------------------------------------- /packages/hypopg.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Hypopg < Pgpm::Package 4 | github "HypoPG/hypopg" 5 | end 6 | -------------------------------------------------------------------------------- /packages/icu_ext.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class IcuExt < Pgpm::Package 4 | github "dverite/icu_ext" 5 | end 6 | -------------------------------------------------------------------------------- /packages/imgsmlr.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Imgsmlr < Pgpm::Package 4 | github "postgrespro/imgsmlr" 5 | end 6 | -------------------------------------------------------------------------------- /packages/index_advisor.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class IndexAdvisor < Pgpm::Package 4 | github "supabase/index_advisor" 5 | end 6 | -------------------------------------------------------------------------------- /packages/ip4r.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Ip4r < Pgpm::Package 4 | github "RhodiumToad/ip4r" 5 | end 6 | -------------------------------------------------------------------------------- /packages/jdbc_fdw.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class JdbcFdw < Pgpm::Package 4 | github "pgspider/jdbc_fdw" 5 | end 6 | -------------------------------------------------------------------------------- /packages/jsquery.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Jsquery < Pgpm::Package 4 | github "postgrespro/jsquery" 5 | end 6 | -------------------------------------------------------------------------------- /packages/kafka_fdw.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class KafkaFdw < Pgpm::Package 4 | github "adjust/kafka_fdw" 5 | end 6 | -------------------------------------------------------------------------------- /packages/log_fdw.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class LogFdw < Pgpm::Package 4 | github "aws/postgresql-logfdw" 5 | end 6 | -------------------------------------------------------------------------------- /packages/logerrors.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Logerrors < Pgpm::Package 4 | github "munakoiso/logerrors" 5 | end 6 | -------------------------------------------------------------------------------- /packages/login_hook.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class LoginHook < Pgpm::Package 4 | github "splendiddata/login_hook" 5 | end 6 | -------------------------------------------------------------------------------- /packages/lower_quantile.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class LowerQuantile < Pgpm::Package 4 | github "tvondra/lower_quantile" 5 | end 6 | -------------------------------------------------------------------------------- /packages/md5hash.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Md5hash < Pgpm::Package 4 | github "tvondra/md5hash" 5 | end 6 | -------------------------------------------------------------------------------- /packages/meta.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Meta < Pgpm::Package 4 | github "aquameta/meta" 5 | end 6 | -------------------------------------------------------------------------------- /packages/mimeo.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Mimeo < Pgpm::Package 4 | github "omniti-labs/mimeo" 5 | end 6 | -------------------------------------------------------------------------------- /packages/mobilitydb.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Mobilitydb < Pgpm::Package 4 | github "MobilityDB/MobilityDB" 5 | end 6 | -------------------------------------------------------------------------------- /packages/mongo_fdw.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class MongoFdw < Pgpm::Package 4 | github "EnterpriseDB/mongo_fdw" 5 | end 6 | -------------------------------------------------------------------------------- /packages/multicorn.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Multicorn < Pgpm::Package 4 | github "pgsql-io/multicorn2" 5 | end 6 | -------------------------------------------------------------------------------- /packages/mysql_fdw.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class MysqlFdw < Pgpm::Package 4 | github "EnterpriseDB/mysql_fdw" 5 | end 6 | -------------------------------------------------------------------------------- /packages/noset.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Noset < Pgpm::Package 4 | git "https://gitlab.com/ongresinc/extensions/noset" 5 | end 6 | -------------------------------------------------------------------------------- /packages/numeral.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Numeral < Pgpm::Package 4 | github "df7cb/postgresql-numeral" 5 | end 6 | -------------------------------------------------------------------------------- /packages/odbc_fdw.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class OdbcFdw < Pgpm::Package 4 | github "CartoDB/odbc_fdw" 5 | end 6 | -------------------------------------------------------------------------------- /packages/ogr_fdw.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class OgrFdw < Pgpm::Package 4 | github "pramsey/pgsql-ogr-fdw" 5 | end 6 | -------------------------------------------------------------------------------- /packages/omnigres/extension_discovery.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "git" 4 | require "parallel" 5 | 6 | module Omnigres 7 | class ExtensionDiscovery 8 | @@extensions = {} 9 | @@git_revisions = {} 10 | @mutex = Mutex.new 11 | 12 | class << self 13 | attr_reader :mutex # Expose a class-level reader for the mutex 14 | end 15 | 16 | def initialize(revision: nil, path: nil) 17 | return if @@extensions[revision] 18 | 19 | suffix = revision ? "-#{revision}" : nil 20 | path ||= Pgpm::Cache.directory.join("omnigres#{suffix}") 21 | self.class.mutex.synchronize do 22 | git = 23 | if File.directory?(path) 24 | g = ::Git.open(path) 25 | g.pull 26 | g 27 | else 28 | ::Git.clone("https://github.com/omnigres/omnigres", path) 29 | end 30 | git.checkout(revision) if revision 31 | @git = git 32 | end 33 | end 34 | 35 | attr_reader :git 36 | 37 | def extension_versions 38 | process_git_log 39 | @@extensions[@git.log.first.sha] 40 | end 41 | 42 | def extension_git_revisions 43 | process_git_log 44 | @@git_revisions[@git.log.first.sha] 45 | end 46 | 47 | private 48 | 49 | def process_git_log 50 | return if @@extensions[@git.log.first.sha] 51 | 52 | # Direct merge commits into master 53 | direct_master_merges = @git.lib.send(:command, "rev-list", "master", "--first-parent").split.map 54 | 55 | # Get versions.txt from all direct merges (we don't want to consider what's inside a merge 56 | # as it may contain versions we never released) 57 | # This is going to create a hash table [name, sha] => version 58 | versions_map = @git.log(:all).path("versions.txt").select { |c| direct_master_merges.include?(c.sha) }.each_with_object({}) do |c, h| 59 | lines = @git.show(c, "versions.txt").split 60 | lines.each do |l| 61 | ext, ver = l.split("=") 62 | h[[ext, c.sha]] = Pgpm::Package::Version.new(ver) 63 | end 64 | end 65 | 66 | # Hash mapping extension names to a list of versions 67 | # name => [versions] 68 | @@extensions[@git.log.first.sha] = versions_map.group_by { |(name, _sha), _ver| name } 69 | .transform_values { |entries| entries.map { |_key, version| version }.uniq } 70 | 71 | # Hash mapping extension versions to SHAs 72 | # [name][ver] => sha 73 | # Note that we're getting the latest merges that contain this version – it doesn't mean that these 74 | # are the merges where those versions were introduced. But that's okay because if they are there, 75 | # they are buildable at least as of those merges and possible at the HEAD of master. 76 | @@git_revisions[@git.log.first.sha] = versions_map.each_with_object({}) do |((name, sha), version), result| 77 | result[name] ||= {} 78 | result[name][version] = sha 79 | end 80 | end 81 | end 82 | end 83 | -------------------------------------------------------------------------------- /packages/omnigres/omni.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class Omni < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "Advanced adapter for Postgres extensions" 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /packages/omnigres/omni_auth.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniAuth < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "Authentication framework" 9 | end 10 | 11 | def build_dependencies 12 | super + ["zlib-devel", Pgpm::Postgres::Distribution.in_scope.package_for(Pgpm::Contrib::Pgcrypto[:latest])] 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /packages/omnigres/omni_aws.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniAws < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "AWS APIs" 9 | end 10 | 11 | def build_dependencies 12 | super + ["zlib-devel", Pgpm::Postgres::Distribution.in_scope.package_for(Pgpm::Contrib::Pgcrypto[:latest])] 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /packages/omnigres/omni_cloudevents.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniCloudevents < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "CloudEvents support" 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /packages/omnigres/omni_containers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniContainers < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "Managing containers" 9 | end 10 | 11 | def build_dependencies 12 | super + ["zlib-devel"] 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /packages/omnigres/omni_http.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniHttp < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "Common HTTP types library" 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /packages/omnigres/omni_httpc.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniHttpc < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "HTTP client" 9 | end 10 | 11 | def build_dependencies 12 | super + ["zlib-devel"] 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /packages/omnigres/omni_httpd.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniHttpd < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "HTTP web server" 9 | end 10 | 11 | def build_dependencies 12 | super + %w[zlib-devel flex bison] 13 | end 14 | 15 | def depends_on_omni? 16 | true 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /packages/omnigres/omni_id.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniId < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "Identity types" 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /packages/omnigres/omni_json.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniJson < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "JSON toolkit" 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /packages/omnigres/omni_ledger.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniLedger < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "Financial ledgering and accounting" 9 | end 10 | 11 | def depends_on_omni? 12 | true 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /packages/omnigres/omni_manifest.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniManifest < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "Improved extension installation" 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /packages/omnigres/omni_mimetypes.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniMimetypes < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "MIME types and file extensions" 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /packages/omnigres/omni_os.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniOs < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "Access to the operating system" 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /packages/omnigres/omni_polyfill.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniPolyfill < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "Provides polyfills for older versions of Postgres" 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /packages/omnigres/omni_python.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniPython < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "First-class Python Development Experience" 9 | end 10 | 11 | def build_dependencies 12 | super + [Pgpm::Postgres::Distribution.in_scope.package_for(Pgpm::Contrib::Plpython3u[:latest])] 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /packages/omnigres/omni_regex.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniRegex < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "Feature-rich regular expresssions" 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /packages/omnigres/omni_schema.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniSchema < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "Application schema management" 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /packages/omnigres/omni_seq.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniSeq < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "Extended Postgres sequence tooling" 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /packages/omnigres/omni_session.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniSession < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "Session management" 9 | end 10 | 11 | def build_dependencies 12 | super + %w[zlib-devel flex bison] 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /packages/omnigres/omni_sql.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniSql < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "Programmatic access to SQL" 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /packages/omnigres/omni_txn.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniTxn < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "Advanced transaction management" 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /packages/omnigres/omni_types.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniTypes < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "Advanced Postgres typing techniques" 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /packages/omnigres/omni_var.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniVar < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "Variable management" 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /packages/omnigres/omni_vfs.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniVfs < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "Virtual File System" 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /packages/omnigres/omni_vfs_types_v1.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniVfsTypesV1 < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "Virtual File System API" 9 | end 10 | 11 | def requires 12 | # FIXME: this handles the special case of this extension being in 13 | # the same folder as omni_vfs. 14 | # In order to configure it, all dependencies of omni_vfs, save for omni_vfs_types_v1, 15 | # must be included. 16 | Pgpm::Package["omnigres/omni_vfs"][:latest].requires.reject { |p| p.name == name } 17 | end 18 | 19 | def native? 20 | # This extension shares the directory with `omni_vfs` which has .c files, 21 | # but it is not a native-code extension itself. 22 | false 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /packages/omnigres/omni_web.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniWeb < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "Web stack primitives" 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /packages/omnigres/omni_xml.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniXml < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "XML toolkit" 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /packages/omnigres/omni_yaml.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Omnigres 4 | class OmniYaml < Pgpm::Package 5 | include Package 6 | 7 | def summary 8 | "YAML toolkit" 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /packages/omnisketch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Omnisketch < Pgpm::Package 4 | github "tvondra/omnisketch" 5 | end 6 | -------------------------------------------------------------------------------- /packages/oracle_fdw.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class OracleFdw < Pgpm::Package 4 | github "laurenz/oracle_fdw" 5 | end 6 | -------------------------------------------------------------------------------- /packages/orafce.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Orafce < Pgpm::Package 4 | github "orafce/orafce" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pagevis.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pagevis < Pgpm::Package 4 | github "hollobon/pagevis" 5 | end 6 | -------------------------------------------------------------------------------- /packages/passwordcheck_cracklib.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PasswordcheckCracklib < Pgpm::Package 4 | github "devrimgunduz/passwordcheck_cracklib" 5 | end 6 | -------------------------------------------------------------------------------- /packages/periods.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Periods < Pgpm::Package 4 | github "xocolatl/periods" 5 | end 6 | -------------------------------------------------------------------------------- /packages/permuteseq.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Permuteseq < Pgpm::Package 4 | github "dverite/permuteseq" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_analytics.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgAnalytics < Pgpm::Package 4 | github "paradedb/pg_analytics" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_auditor.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgAuditor < Pgpm::Package 4 | github "kouber/pg_auditor" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_auth_mon.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgAuthMon < Pgpm::Package 4 | github "RafiaSabih/pg_auth_mon" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_background.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgBackground < Pgpm::Package 4 | github "vibhorkum/pg_background" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_base58.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgBase58 < Pgpm::Package 4 | github "Fell-x27/pg_base58" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_bestmatch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgBestmatch < Pgpm::Package 4 | github "tensorchord/pg_bestmatch.rs" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_bigm.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgBigm < Pgpm::Package 4 | github "pgbigm/pg_bigm" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_bulkload.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgBulkload < Pgpm::Package 4 | github "ossc-db/pg_bulkload" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_cardano.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgCardano < Pgpm::Package 4 | github "Fell-x27/pg_cardano" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_catcheck.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgCatcheck < Pgpm::Package 4 | github "EnterpriseDB/pg_catcheck" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_cheat_funcs.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgCheatFuncs < Pgpm::Package 4 | github "MasaoFujii/pg_cheat_funcs" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_checksums.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgChecksums < Pgpm::Package 4 | github "credativ/pg_checksums" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_crash.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgCrash < Pgpm::Package 4 | github "cybertec-postgresql/pg_crash" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_cron.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgCron < Pgpm::Package 4 | github "citusdata/pg_cron" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_dbms_job.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgDbmsJob < Pgpm::Package 4 | github "MigOpsRepos/pg_dbms_job" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_dbms_lock.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgDbmsLock < Pgpm::Package 4 | github "HexaCluster/pg_dbms_lock" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_dbms_metadata.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgDbmsMetadata < Pgpm::Package 4 | github "HexaCluster/pg_dbms_metadata" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_dirtyread.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgDirtyread < Pgpm::Package 4 | github "df7cb/pg_dirtyread" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_drop_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgDropEvents < Pgpm::Package 4 | github "bolajiwahab/pg_drop_events" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_duckdb.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgDuckdb < Pgpm::Package 4 | github "duckdb/pg_duckdb" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_duration.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgDuration < Pgpm::Package 4 | github "jkosh44/pg_duration" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_extra_time.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgExtraTime < Pgpm::Package 4 | github "bigsmoke/pg_extra_time" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_fact_loader.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgFactLoader < Pgpm::Package 4 | github "enova/pg_fact_loader" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_failover_slots.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgFailoverSlots < Pgpm::Package 4 | github "EnterpriseDB/pg_failover_slots" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_fio.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgFio < Pgpm::Package 4 | github "csimsek/pgsql-fio" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_fkpart.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgFkpart < Pgpm::Package 4 | github "lemoineat/pg_fkpart" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_geohash.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgGeohash < Pgpm::Package 4 | github "jistok/pg_geohash" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_graphql.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgGraphql < Pgpm::Package 4 | github "supabase/pg_graphql" 5 | 6 | def summary 7 | "GraphQL support for PostgreSQL" 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /packages/pg_hashids.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgHashids < Pgpm::Package 4 | github "iCyberon/pg_hashids" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_hashlib.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgHashlib < Pgpm::Package 4 | github "markokr/pghashlib" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_hint_plan.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgHintPlan < Pgpm::Package 4 | github "ossc-db/pg_hint_plan" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_html5_email_address.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgHtml5EmailAddress < Pgpm::Package 4 | github "bigsmoke/pg_html5_email_address" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_idkit.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgIdkit < Pgpm::Package 4 | github "VADOSWARE/pg_idkit" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_incremental.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgIncremental < Pgpm::Package 4 | github "crunchydata/pg_incremental" 5 | 6 | def requires 7 | super + [Pgpm::Package["pg_cron"][:latest]] 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /packages/pg_ivm.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgIvm < Pgpm::Package 4 | github "sraoss/pg_ivm" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_jobmon.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgJobmon < Pgpm::Package 4 | github "omniti-labs/pg_jobmon" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_jsonschema.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgJsonschema < Pgpm::Package 4 | github "supabase/pg_jsonschema" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_later.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgLater < Pgpm::Package 4 | github "tembo-io/pg_later" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_math.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgMath < Pgpm::Package 4 | github "chanukyasds/pg_math" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_mooncake.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgMooncake < Pgpm::Package 4 | github "Mooncake-Labs/pg_mooncake" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_net.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgNet < Pgpm::Package 4 | github "supabase/pg_net" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_orphaned.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgOrphaned < Pgpm::Package 4 | github "bdrouvot/pg_orphaned" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_parquet.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgParquet < Pgpm::Package 4 | github "CrunchyData/pg_parquet" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_partman.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgPartman < Pgpm::Package 4 | github "pgpartman/pg_partman" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_permissions.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgPermissions < Pgpm::Package 4 | github "cybertec-postgresql/pg_permissions" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_polyline.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgPolyline < Pgpm::Package 4 | github "yihong0618/pg_polyline" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_proctab.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgProctab < Pgpm::Package 4 | github "markwkm/pg_proctab" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_profile.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgProfile < Pgpm::Package 4 | github "zubkov-andrei/pg_profile" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_protobuf.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgProtobuf < Pgpm::Package 4 | github "afiskon/pg_protobuf" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_qualstats.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgQualstats < Pgpm::Package 4 | github "powa-team/pg_qualstats" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_rational.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgRational < Pgpm::Package 4 | github "begriffs/pg_rational" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_readme.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgReadme < Pgpm::Package 4 | github "bigsmoke/pg_readme" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_readonly.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgReadonly < Pgpm::Package 4 | github "pierreforstmann/pg_readonly" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_relusage.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgRelusage < Pgpm::Package 4 | github "adept/pg_relusage" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_repack.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgRepack < Pgpm::Package 4 | github "reorg/pg_repack" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_rrule.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgRrule < Pgpm::Package 4 | github "petropavel13/pg_rrule" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_savior.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgSavior < Pgpm::Package 4 | github "viggy28/pg_savior" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_search.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgSearch < Pgpm::Package 4 | github "paradedb/paradedb" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_session_jwt.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgSessionJwt < Pgpm::Package 4 | github "neondatabase/pg_session_jwt" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_show_plans.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgShowPlans < Pgpm::Package 4 | github "cybertec-postgresql/pg_show_plans" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_similarity.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgSimilarity < Pgpm::Package 4 | github "eulerto/pg_similarity" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_smtp_client.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgSmtpClient < Pgpm::Package 4 | github "brianpursley/pg_smtp_client" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_snakeoil.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgSnakeoil < Pgpm::Package 4 | github "credativ/pg_snakeoil" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_sphere.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgSphere < Pgpm::Package 4 | github "postgrespro/pgsphere" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_sqlog.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgSqlog < Pgpm::Package 4 | github "kouber/pg_sqlog" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_squeeze.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgSqueeze < Pgpm::Package 4 | github "cybertec-postgresql/pg_squeeze" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_stat_kcache.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgStatKcache < Pgpm::Package 4 | github "powa-team/pg_stat_kcache" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_stat_monitor.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgStatMonitor < Pgpm::Package 4 | github "percona/pg_stat_monitor" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_statement_rollback.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgStatementRollback < Pgpm::Package 4 | github "lzlabs/pg_statement_rollback" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_store_plans.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgStorePlans < Pgpm::Package 4 | github "ossc-db/pg_store_plans" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_strom.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgStrom < Pgpm::Package 4 | github "heterodb/pg-strom" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_summarize.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgSummarize < Pgpm::Package 4 | github "HexaCluster/pg_summarize" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_task.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgTask < Pgpm::Package 4 | github "RekGRpth/pg_task" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_tde.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgTde < Pgpm::Package 4 | github "Percona-Lab/pg_tde" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_text_semver.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgTextSemver < Pgpm::Package 4 | github "bigsmoke/pg_text_semver" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_tiktoken.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgTiktoken < Pgpm::Package 4 | github "kelvich/pg_tiktoken" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_tle.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgTle < Pgpm::Package 4 | github "aws/pg_tle" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_top.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgTop < Pgpm::Package 4 | git "https://gitlab.com/pg_top/pg_top" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_track_settings.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgTrackSettings < Pgpm::Package 4 | github "rjuju/pg_track_settings" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_upless.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgUpless < Pgpm::Package 4 | github "rodo/pg_upless" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_uuidv7.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgUuidv7 < Pgpm::Package 4 | github "fboulnois/pg_uuidv7" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_wait_sampling.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgWaitSampling < Pgpm::Package 4 | github "postgrespro/pg_wait_sampling" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pg_xenophile.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgXenophile < Pgpm::Package 4 | github "bigsmoke/pg_xenophile" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgaudit.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgaudit < Pgpm::Package 4 | github "pgaudit/pgaudit" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgauditlogtofile.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgauditlogtofile < Pgpm::Package 4 | github "fmbiete/pgauditlogtofile" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgautofailover.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgautofailover < Pgpm::Package 4 | github "hapostgres/pg_auto_failover" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgbouncer_fdw.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgbouncerFdw < Pgpm::Package 4 | github "CrunchyData/pgbouncer_fdw" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgcozy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgcozy < Pgpm::Package 4 | github "vventirozos/pgcozy" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgdd.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgdd < Pgpm::Package 4 | github "rustprooflabs/pgdd" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgemailaddr.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgemailaddr < Pgpm::Package 4 | github "petere/pgemailaddr" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgextwlist.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgextwlist < Pgpm::Package 4 | github "dimitri/pgextwlist" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgfaceting.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgfaceting < Pgpm::Package 4 | github "cybertec-postgresql/pgfaceting" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgfincore.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgfincore < Pgpm::Package 4 | github "klando/pgfincore" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgjwt.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgjwt < Pgpm::Package 4 | github "michelp/pgjwt" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgl_ddl_deploy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PglDdlDeploy < Pgpm::Package 4 | github "enova/pgl_ddl_deploy" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pglite_fusion.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgliteFusion < Pgpm::Package 4 | github "frectonz/pglite-fusion" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pglogical.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pglogical < Pgpm::Package 4 | github "2ndQuadrant/pglogical" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pglogical_origin.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PglogicalOrigin < Pgpm::Package 4 | github "2ndQuadrant/pglogical" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pglogical_ticker.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PglogicalTicker < Pgpm::Package 4 | github "enova/pglogical_ticker" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgmemcache.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgmemcache < Pgpm::Package 4 | github "ohmu/pgmemcache" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgmeminfo.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgmeminfo < Pgpm::Package 4 | github "okbob/pgmeminfo" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgml.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgml < Pgpm::Package 4 | github "postgresml/postgresml" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgmp.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgmp < Pgpm::Package 4 | github "dvarrazzo/pgmp", tag_prefix: "rel-" 5 | 6 | def build_dependencies 7 | super + %w[gmp-devel] 8 | end 9 | 10 | def dependencies 11 | super + %w[gmp] 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /packages/pgmq.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgmq < Pgpm::Package 4 | github "tembo-io/pgmq" 5 | 6 | def source 7 | Pathname(File.join(super, "pgmq-extension")) 8 | end 9 | 10 | def pgxn_meta_json_path 11 | File.join(source, "META.json.in") 12 | end 13 | 14 | def pgxn_meta_json 15 | @pgxn_meta_json ||= Oj.load(File.read(pgxn_meta_json_path).gsub(/@@VERSION@@/, version.to_s)) 16 | end 17 | 18 | def source_url_directory_name 19 | "pgmq-#{version}/pgmq-extension" 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /packages/pgnodemx.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgnodemx < Pgpm::Package 4 | github "CrunchyData/pgnodemx" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgpcre.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgpcre < Pgpm::Package 4 | github "petere/pgpcre" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgpdf.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgpdf < Pgpm::Package 4 | github "Florents-Tselai/pgpdf" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgq.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgq < Pgpm::Package 4 | github "pgq/pgq" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgqr.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgqr < Pgpm::Package 4 | github "AbdulYadi/pgqr" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgroonga.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgroonga < Pgpm::Package 4 | github "pgroonga/pgroonga" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgroonga_database.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgroongaDatabase < Pgpm::Package 4 | github "pgroonga/pgroonga" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgrouting.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgrouting < Pgpm::Package 4 | github "pgRouting/pgrouting" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgsmcrypto.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgsmcrypto < Pgpm::Package 4 | github "zhuobie/pgsmcrypto" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgsodium.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgsodium < Pgpm::Package 4 | github "michelp/pgsodium" 5 | 6 | def build_dependencies 7 | deps = case Pgpm::OS.in_scope.class.name 8 | when "debian", "ubuntu" 9 | ["libsodium-dev (>= 1.0.18)"] 10 | when "rocky+epel-9", "redhat", "fedora" 11 | ["libsodium-devel >= 1.0.18"] 12 | end 13 | super + deps 14 | end 15 | 16 | def dependencies 17 | deps = case Pgpm::OS.in_scope.class.name 18 | when "debian", "ubuntu" 19 | ["libsodium (>= 1.0.18)"] 20 | when "rocky+epel-9", "redhat", "fedora" 21 | ["libsodium >= 1.0.18"] 22 | end 23 | super + deps 24 | end 25 | 26 | def broken? 27 | version >= "3.0.0" && Pgpm::Postgres::Distribution.in_scope.major_version < 14 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /packages/pgsql_tweaks.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PgsqlTweaks < Pgpm::Package 4 | github "sjstoelting/pgsql-tweaks" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgtap.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgtap < Pgpm::Package 4 | github "theory/pgtap" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgtt.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgtt < Pgpm::Package 4 | github "darold/pgtt" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pguecc.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pguecc < Pgpm::Package 4 | github "ameensol/pg-ecdsa" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pgvector.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pgvector < Pgpm::Package 4 | github "pgvector/pgvector" 5 | end 6 | -------------------------------------------------------------------------------- /packages/plan_filter.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PlanFilter < Pgpm::Package 4 | github "pgexperts/pg_plan_filter" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pldbgapi.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pldbgapi < Pgpm::Package 4 | github "EnterpriseDB/pldebugger" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pljava.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pljava < Pgpm::Package 4 | github "tada/pljava" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pllua.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pllua < Pgpm::Package 4 | github "pllua/pllua" 5 | end 6 | -------------------------------------------------------------------------------- /packages/plluau.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Plluau < Pgpm::Package 4 | github "pllua/pllua" 5 | end 6 | -------------------------------------------------------------------------------- /packages/plpgsql_check.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "semver_dialects" 4 | 5 | class PlpgsqlCheck < Pgpm::Package 6 | github "okbob/plpgsql_check" 7 | end 8 | -------------------------------------------------------------------------------- /packages/plprofiler.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Plprofiler < Pgpm::Package 4 | github "bigsql/plprofiler" 5 | end 6 | -------------------------------------------------------------------------------- /packages/plproxy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Plproxy < Pgpm::Package 4 | github "plproxy/plproxy" 5 | end 6 | -------------------------------------------------------------------------------- /packages/plprql.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Plprql < Pgpm::Package 4 | github "kaspermarstal/plprql" 5 | end 6 | -------------------------------------------------------------------------------- /packages/plr.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Plr < Pgpm::Package 4 | github "postgres-plr/plr" 5 | end 6 | -------------------------------------------------------------------------------- /packages/plsh.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Plsh < Pgpm::Package 4 | github "petere/plsh" 5 | end 6 | -------------------------------------------------------------------------------- /packages/plv8.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Plv8 < Pgpm::Package 4 | github "plv8/plv8" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pointcloud.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Pointcloud < Pgpm::Package 4 | github "pgpointcloud/pointcloud" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pointcloud_postgis.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PointcloudPostgis < Pgpm::Package 4 | github "pgpointcloud/pointcloud" 5 | end 6 | -------------------------------------------------------------------------------- /packages/powa.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Powa < Pgpm::Package 4 | github "powa-team/powa" 5 | end 6 | -------------------------------------------------------------------------------- /packages/pre_prepare.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PrePrepare < Pgpm::Package 4 | github "dimitri/preprepare" 5 | end 6 | -------------------------------------------------------------------------------- /packages/prefix.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Prefix < Pgpm::Package 4 | github "dimitri/prefix" 5 | end 6 | -------------------------------------------------------------------------------- /packages/prioritize.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Prioritize < Pgpm::Package 4 | github "schmiddy/pg_prioritize" 5 | end 6 | -------------------------------------------------------------------------------- /packages/q3c.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Q3c < Pgpm::Package 4 | github "segasai/q3c" 5 | end 6 | -------------------------------------------------------------------------------- /packages/quantile.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Quantile < Pgpm::Package 4 | github "tvondra/quantile" 5 | end 6 | -------------------------------------------------------------------------------- /packages/random.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Random < Pgpm::Package 4 | github "tvondra/random" 5 | end 6 | -------------------------------------------------------------------------------- /packages/rdkit.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Rdkit < Pgpm::Package 4 | github "rdkit/rdkit" 5 | end 6 | -------------------------------------------------------------------------------- /packages/redis.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Redis < Pgpm::Package 4 | github "brettlaforge/pg_redis_pubsub" 5 | end 6 | -------------------------------------------------------------------------------- /packages/redis_fdw.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class RedisFdw < Pgpm::Package 4 | github "pg-redis-fdw/redis_fdw" 5 | end 6 | -------------------------------------------------------------------------------- /packages/repmgr.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Repmgr < Pgpm::Package 4 | github "EnterpriseDB/repmgr" 5 | end 6 | -------------------------------------------------------------------------------- /packages/roaringbitmap.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Roaringbitmap < Pgpm::Package 4 | github "ChenHuajun/pg_roaringbitmap" 5 | end 6 | -------------------------------------------------------------------------------- /packages/rum.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Rum < Pgpm::Package 4 | github "postgrespro/rum" 5 | end 6 | -------------------------------------------------------------------------------- /packages/safeupdate.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Safeupdate < Pgpm::Package 4 | github "eradman/pg-safeupdate" 5 | end 6 | -------------------------------------------------------------------------------- /packages/schedoc.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Schedoc < Pgpm::Package 4 | github "ZeroGachis/pg_schedoc" 5 | end 6 | -------------------------------------------------------------------------------- /packages/semver.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Semver < Pgpm::Package 4 | github "theory/pg-semver" 5 | end 6 | -------------------------------------------------------------------------------- /packages/sequential_uuids.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class SequentialUuids < Pgpm::Package 4 | github "tvondra/sequential-uuids" 5 | end 6 | -------------------------------------------------------------------------------- /packages/session_variable.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class SessionVariable < Pgpm::Package 4 | github "splendiddata/session_variable" 5 | end 6 | -------------------------------------------------------------------------------- /packages/set_user.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class SetUser < Pgpm::Package 4 | github "pgaudit/set_user" 5 | end 6 | -------------------------------------------------------------------------------- /packages/shacrypt.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Shacrypt < Pgpm::Package 4 | github "dverite/postgres-shacrypt" 5 | end 6 | -------------------------------------------------------------------------------- /packages/smlar.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Smlar < Pgpm::Package 4 | github "jirutka/smlar" 5 | end 6 | -------------------------------------------------------------------------------- /packages/sqlite_fdw.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class SqliteFdw < Pgpm::Package 4 | github "pgspider/sqlite_fdw" 5 | end 6 | -------------------------------------------------------------------------------- /packages/sslutils.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Sslutils < Pgpm::Package 4 | github "EnterpriseDB/sslutils" 5 | end 6 | -------------------------------------------------------------------------------- /packages/supabase_vault.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class SupabaseVault < Pgpm::Package 4 | github "supabase/vault" 5 | end 6 | -------------------------------------------------------------------------------- /packages/supautils.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Supautils < Pgpm::Package 4 | github "supabase/supautils" 5 | end 6 | -------------------------------------------------------------------------------- /packages/system_stats.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class SystemStats < Pgpm::Package 4 | github "EnterpriseDB/system_stats" 5 | end 6 | -------------------------------------------------------------------------------- /packages/table_log.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class TableLog < Pgpm::Package 4 | github "df7cb/table_log" 5 | end 6 | -------------------------------------------------------------------------------- /packages/table_version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class TableVersion < Pgpm::Package 4 | github "linz/postgresql-tableversion" 5 | end 6 | -------------------------------------------------------------------------------- /packages/tdigest.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Tdigest < Pgpm::Package 4 | github "tdunning/t-digest" 5 | end 6 | -------------------------------------------------------------------------------- /packages/tds_fdw.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class TdsFdw < Pgpm::Package 4 | github "tds-fdw/tds_fdw" 5 | end 6 | -------------------------------------------------------------------------------- /packages/temporal_tables.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "semver_dialects" 4 | 5 | class TemporalTables < Pgpm::Package 6 | github "arkhipov/temporal_tables" 7 | end 8 | -------------------------------------------------------------------------------- /packages/timeit.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Timeit < Pgpm::Package 4 | github "joelonsql/pg-timeit" 5 | end 6 | -------------------------------------------------------------------------------- /packages/timescale/timescaledb.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Timescale 4 | class Timescaledb < Pgpm::Package 5 | github "timescale/timescaledb" 6 | 7 | def self.package_versions 8 | # TODO: ensure non-compatible versions are handled better 9 | # in version comparison 10 | # For now, this helps with handling `loader-2.11.0p1` version 11 | super.select { |v| v.to_s =~ /^(\d+\.\d+\.\d+)$/ } 12 | end 13 | 14 | def description 15 | "An open-source time-series SQL database optimized for fast ingest and " \ 16 | "complex queries" 17 | end 18 | 19 | def summary 20 | "TimescaleDB is an open-source database designed to make SQL " \ 21 | "scalable for time-series data. It is engineered up from PostgreSQL " \ 22 | "and packaged as a PostgreSQL extension, providing automatic " \ 23 | "partitioning across time and space (partitioning key), as well as " \ 24 | "full SQL support." 25 | end 26 | 27 | def dependencies 28 | deps = case Pgpm::OS.in_scope.class.name 29 | when "rocky+epel-9", "redhat", "fedora" 30 | ["openssl"] 31 | end 32 | super + deps 33 | end 34 | 35 | def build_dependencies 36 | deps = case Pgpm::OS.in_scope.class.name 37 | when "debian", "ubuntu" 38 | %w[libssl-dev cmake] 39 | when "rocky+epel-9", "redhat", "fedora" 40 | %w[openssl-devel cmake] 41 | end 42 | super + deps 43 | end 44 | 45 | def configure_steps 46 | case Pgpm::OS.in_scope.class.name 47 | when "debian", "ubuntu" 48 | ["dh_auto_configure -- -DCMAKE_BUILD_TYPE=\"Release\""] 49 | else 50 | super 51 | end 52 | end 53 | 54 | def build_steps 55 | case Pgpm::OS.in_scope.class.name 56 | when "debian", "ubuntu" 57 | ["dh_auto_build"] 58 | when "rocky+epel-9", "redhat", "fedora" 59 | [ 60 | "./bootstrap -DPG_CONFIG=$PG_CONFIG #{bootstrap_flags.map { |f| "-D#{f}" }.join(" ")}", 61 | "cmake --build build --parallel" 62 | ] 63 | end 64 | end 65 | 66 | def install_steps 67 | case Pgpm::OS.in_scope.class.name 68 | when "rocky+epel-9", "redhat", "fedora" 69 | ["DESTDIR=$PGPM_INSTALL_ROOT cmake --build build --target install"] 70 | else 71 | super 72 | end 73 | end 74 | 75 | protected 76 | 77 | def bootstrap_flags 78 | [] 79 | end 80 | end 81 | end 82 | -------------------------------------------------------------------------------- /packages/timescale/timescaledb_apache2.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Timescale 4 | # TODO: do we want this "subpackage" to be some kind of "flavour" in pgpm? 5 | class TimescaledbApache2 < Timescaledb 6 | # TODO: can pgpm handle subclassing here better? 7 | github "timescale/timescaledb" 8 | 9 | def extension_name 10 | "timescaledb" 11 | end 12 | 13 | def source_url_directory_name 14 | "timescaledb-2.17.2" 15 | end 16 | 17 | def license 18 | "Apache 2.0" 19 | end 20 | 21 | protected 22 | 23 | def bootstrap_flags 24 | ["APACHE_ONLY=1"] 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /packages/timescaledb_toolkit.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class TimescaledbToolkit < Pgpm::Package 4 | github "timescale/timescaledb-toolkit" 5 | end 6 | -------------------------------------------------------------------------------- /packages/timeseries.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Timeseries < Pgpm::Package 4 | github "tembo-io/pg_timeseries" 5 | end 6 | -------------------------------------------------------------------------------- /packages/timestamp9.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Timestamp9 < Pgpm::Package 4 | github "optiver/timestamp9" 5 | end 6 | -------------------------------------------------------------------------------- /packages/toastinfo.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Toastinfo < Pgpm::Package 4 | github "credativ/toastinfo" 5 | end 6 | -------------------------------------------------------------------------------- /packages/topn.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Topn < Pgpm::Package 4 | github "citusdata/postgresql-topn" 5 | end 6 | -------------------------------------------------------------------------------- /packages/uint.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Uint < Pgpm::Package 4 | github "petere/pguint" 5 | end 6 | -------------------------------------------------------------------------------- /packages/uint128.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Uint128 < Pgpm::Package 4 | github "pg-uint/pg-uint128" 5 | end 6 | -------------------------------------------------------------------------------- /packages/unit.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Unit < Pgpm::Package 4 | github "df7cb/postgresql-unit" 5 | end 6 | -------------------------------------------------------------------------------- /packages/uri.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Uri < Pgpm::Package 4 | github "petere/pguri" 5 | end 6 | -------------------------------------------------------------------------------- /packages/url_encode.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class UrlEncode < Pgpm::Package 4 | github "okbob/url_encode" 5 | end 6 | -------------------------------------------------------------------------------- /packages/vasco.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Vasco < Pgpm::Package 4 | github "Florents-Tselai/vasco" 5 | end 6 | -------------------------------------------------------------------------------- /packages/vchord.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Vchord < Pgpm::Package 4 | github "tensorchord/VectorChord" 5 | end 6 | -------------------------------------------------------------------------------- /packages/vectorize.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Vectorize < Pgpm::Package 4 | github "tembo-io/pg_vectorize" 5 | end 6 | -------------------------------------------------------------------------------- /packages/vectorscale.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Vectorscale < Pgpm::Package 4 | github "timescale/pgvectorscale" 5 | end 6 | -------------------------------------------------------------------------------- /packages/wal2json.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Wal2json < Pgpm::Package 4 | github "eulerto/wal2json" 5 | end 6 | -------------------------------------------------------------------------------- /packages/wal2mongo.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Wal2mongo < Pgpm::Package 4 | github "HighgoSoftware/wal2mongo" 5 | end 6 | -------------------------------------------------------------------------------- /packages/wrappers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Wrappers < Pgpm::Package 4 | github "supabase/wrappers" 5 | end 6 | -------------------------------------------------------------------------------- /packages/xxhash.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Xxhash < Pgpm::Package 4 | github "hatarist/pg_xxhash" 5 | end 6 | -------------------------------------------------------------------------------- /packages/zhparser.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Zhparser < Pgpm::Package 4 | github "amutu/zhparser" 5 | end 6 | -------------------------------------------------------------------------------- /packages/zstd.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Zstd < Pgpm::Package 4 | github "grahamedgecombe/pgzstd" 5 | end 6 | -------------------------------------------------------------------------------- /pgpm.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "lib/pgpm/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "pgpm" 7 | spec.version = Pgpm::VERSION 8 | spec.authors = ["Yurii Rashkovskii"] 9 | spec.email = ["yrashk@gmail.com"] 10 | 11 | spec.summary = "Postgres Package Manager" 12 | spec.homepage = "https://postgres.pm" 13 | spec.license = "Apache-2.0" 14 | spec.required_ruby_version = ">= 3.3.0" 15 | 16 | # spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'" 17 | 18 | spec.metadata["homepage_uri"] = spec.homepage 19 | spec.metadata["source_code_uri"] = "https://github.com/postgres-pm/postgres-om" 20 | # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here." 21 | 22 | # Specify which files should be added to the gem when it is released. 23 | spec.files = Dir.glob(["exe/*", "lib/**/**", "sig/**/**"]) 24 | spec.bindir = "exe" 25 | spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } 26 | spec.require_paths = ["lib"] 27 | 28 | # Uncomment to register a new dependency of your gem 29 | # spec.add_dependency "example-gem", "~> 1.0" 30 | 31 | spec.add_dependency "dry-cli", "~> 1.1.0" 32 | spec.add_dependency "dry-inflector", "~> 1.1.0" 33 | spec.add_dependency "git", "~> 2.3.0" 34 | spec.add_dependency "lspace", "~> 0.14" 35 | spec.add_dependency "minitar", "~> 1.0.2" 36 | spec.add_dependency "nokogiri", "~> 1.16" 37 | spec.add_dependency "oj", "~> 3.16.6" 38 | spec.add_dependency "parallel", "~> 1.26.3" 39 | spec.add_dependency "perfect_toml", "~> 0.9.0" 40 | spec.add_dependency "progress", "~> 3.6.0" 41 | spec.add_dependency "semver_dialects", "~> 3.4.3" 42 | spec.add_dependency "tty-command", "~> 0.10.1" 43 | spec.add_dependency "xdg", [">= 8.7.0", "< 10"] 44 | spec.add_dependency "zeitwerk", "~> 2.6.18" 45 | spec.add_dependency "zlib", "~> 3.1.1" 46 | 47 | # For more information and examples about making a new gem, check out our 48 | # guide at: https://bundler.io/guides/creating_gem.html 49 | end 50 | -------------------------------------------------------------------------------- /pigsty.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require "bundler/setup" 5 | require "active_support/core_ext/string/inflections" 6 | require "pgpm" 7 | require "csv" 8 | require "open-uri" 9 | 10 | Pgpm.load_packages 11 | 12 | URI.open("https://raw.githubusercontent.com/pgsty/extension/refs/heads/main/data/pigsty.csv") do |f| 13 | i = 0 14 | CSV.foreach(f, headers: true) do |row| 15 | next unless row["url"] =~ /github/ || row["url"] =~ /gitlab/ 16 | 17 | origin = row["url"] 18 | if row["url"] =~ /github/ 19 | github = origin.match(%r{https://github\.com/([^/]+)/([^/]+)}).captures.join("/") 20 | origin = "github \"#{github}\"" 21 | else 22 | origin = "git \"#{origin}\"" 23 | end 24 | name = row["name"] 25 | 26 | next if Pgpm::Package.find do |pkg| 27 | origin =~ /github/ && 28 | pkg.respond_to?(:github_config) && pkg.github_config&.name == github 29 | end 30 | 31 | next if File.exist?("packages/#{name}.rb") 32 | 33 | i += 1 34 | classname = name.camelize 35 | new_class = <<~CLASS 36 | class #{classname} < Pgpm::Package 37 | #{origin} 38 | end 39 | CLASS 40 | File.write("packages/#{name}.rb", new_class) 41 | puts name 42 | end 43 | puts "#{i} packages imported" 44 | end 45 | -------------------------------------------------------------------------------- /sig/pgpm.rbs: -------------------------------------------------------------------------------- 1 | module Pgpm 2 | VERSION: String 3 | # See the writing guide of rbs: https://github.com/ruby/rbs#guides 4 | end 5 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "pgpm" 4 | 5 | require "minitest/autorun" 6 | -------------------------------------------------------------------------------- /test/test_pgpm.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "test_helper" 4 | 5 | class TestPgpm < Minitest::Test 6 | def test_that_it_has_a_version_number 7 | refute_nil ::Pgpm::VERSION 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /test/test_pgpm_package_version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "test_helper" 4 | 5 | class TestPgpmPackageVersion < Minitest::Test 6 | def test_converts_to_string 7 | assert_equal Pgpm::Package::Version.new("1.2.103").to_s, "1.2.103" 8 | end 9 | 10 | def test_equality_with_string 11 | assert_equal Pgpm::Package::Version.new("1.2.103"), "1.2.103" 12 | end 13 | 14 | def test_hashes 15 | assert_equal ({ Pgpm::Package::Version.new("1.2.103") => "yes" }[Pgpm::Package::Version.new("1.2.103")]), "yes" 16 | end 17 | 18 | def test_compares 19 | assert Pgpm::Package::Version.new("1.2.103") > Pgpm::Package::Version.new("1.2.3") 20 | end 21 | end 22 | --------------------------------------------------------------------------------