Compare commits
133 Commits
f4ebad4394
...
master
Author | SHA1 | Date | |
---|---|---|---|
731a36d700
|
|||
8908b8ae93
|
|||
1d81fea1a3
|
|||
e2debec6d7
|
|||
d043ba8844
|
|||
e1ece39147
|
|||
15cf346c61
|
|||
468852410e
|
|||
b5e6e3a2d6
|
|||
2f46303a6d
|
|||
c7e300dc91
|
|||
bb0748b400 | |||
6290be859d
|
|||
f395d57b33
|
|||
8168804d71
|
|||
d9bfd2941c
|
|||
ebbdb6f0f7
|
|||
f758ea7904
|
|||
00cc58f87e
|
|||
2a78256933
|
|||
ae63ff0cc0
|
|||
5b4caa8ff7
|
|||
3dde41e0d4
|
|||
74da0eb391
|
|||
6ead225e88
|
|||
1418e0ae46
|
|||
4f74c2ec10
|
|||
14cc805dcf
|
|||
42b9b671e1
|
|||
e0ca80db32
|
|||
4ce20e3dd9
|
|||
6d0248b4f8
|
|||
c81cabfcbf
|
|||
3b7b15f381
|
|||
f8ef93fde7
|
|||
6ba319c3b6
|
|||
ddda240e40
|
|||
8351be053c
|
|||
a98a6f8574
|
|||
47f27394de
|
|||
7c9c890056
|
|||
7e59a8460d
|
|||
bc3ba48d85
|
|||
3d81917627
|
|||
cd28e6fb90
|
|||
16c7063224
|
|||
cd15b25db1
|
|||
e5bde183a5
|
|||
4c06ae274b
|
|||
c8643a2fd4
|
|||
45472a9088
|
|||
2802194063
|
|||
7edb811dc2
|
|||
a25655c2b2
|
|||
34d7dbd68f
|
|||
49cbda6027
|
|||
eb68629653
|
|||
6a063b2cc4
|
|||
e9504fb8e5
|
|||
ef0a5b5958
|
|||
49d6718fee
|
|||
3414a69bc8 | |||
9770cc8829 | |||
0023fe0337 | |||
24e62c3439 | |||
64233c4c63 | |||
396a536b3a | |||
f51a0418ff | |||
fa6d93c5ca | |||
6c0e2c2d24 | |||
58a1b8864c
|
|||
8a69240d88
|
|||
3a6d17952b
|
|||
4105ffa91f
|
|||
5e161c3dad
|
|||
f3beee3e19
|
|||
7b5598a02e
|
|||
d5df676df7
|
|||
f4b7883cf2
|
|||
69b24c6cfa | |||
7c499bd3f7 | |||
ec704e267b | |||
840290491f | |||
a7114618c1 | |||
77c9a2ab54
|
|||
c2b98ba395
|
|||
2126488066
|
|||
6983304b9d
|
|||
258604f22d
|
|||
fd649b66f5
|
|||
6b15ccd0f5
|
|||
5a9e87cd5f
|
|||
43ebbc5e67
|
|||
69ba04a731
|
|||
028f64d25a
|
|||
1bc410d86d | |||
868f6c36a5
|
|||
bed90e3e02
|
|||
a0788d2f3a
|
|||
df4c9b4ae9
|
|||
e0b98189eb
|
|||
47e6c49ae2
|
|||
d63e657948
|
|||
6e313e2272 | |||
6a81f0959d
|
|||
341eafcbf2
|
|||
f564676cb6
|
|||
04b24eeb99
|
|||
bae3b8e90e
|
|||
6f5eaf9650
|
|||
691ddba017
|
|||
79bdca04e2
|
|||
34b10f41aa
|
|||
dbf14caee2
|
|||
b64a66a20c
|
|||
ae0048ef3d
|
|||
f46a16b4a0
|
|||
0385dbbe53
|
|||
9c85c52599
|
|||
484d170b24
|
|||
7becd04148
|
|||
c7a527e010
|
|||
6b634b4055
|
|||
a24f1b436e
|
|||
bd84f6bbf0 | |||
ad02a3fa38
|
|||
d07825f081
|
|||
49cb7d27eb
|
|||
6719d2d81d
|
|||
70a636a804
|
|||
13d0def37a
|
|||
ef9942fe99
|
|||
5b26e7dca8
|
37
.gitea/workflows/build.yml
Normal file
37
.gitea/workflows/build.yml
Normal file
@ -0,0 +1,37 @@
|
||||
name: Build
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
audit:
|
||||
runs-on: buildenv
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: hlint src lib tests
|
||||
|
||||
test:
|
||||
runs-on: buildenv
|
||||
steps:
|
||||
- name: Set up environment
|
||||
run: |
|
||||
apt-get update -y
|
||||
apt-get upgrade -y
|
||||
apt-get install -y pkg-config liblzma-dev
|
||||
- uses: actions/checkout@v4
|
||||
- run: cabal update
|
||||
- run: cabal test --test-show-details=streaming
|
||||
|
||||
release:
|
||||
runs-on: buildenv
|
||||
steps:
|
||||
- name: Set up environment
|
||||
run: |
|
||||
apt-get update -y
|
||||
apt-get upgrade -y
|
||||
apt-get install -y pkg-config liblzma-dev
|
||||
- uses: actions/checkout@v4
|
||||
- run: cabal update
|
||||
- run: cabal build
|
29
.gitea/workflows/deploy.yaml
Normal file
29
.gitea/workflows/deploy.yaml
Normal file
@ -0,0 +1,29 @@
|
||||
name: Deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '**'
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: buildenv
|
||||
steps:
|
||||
- name: Set up environment
|
||||
run: |
|
||||
apt-get update -y
|
||||
apt-get upgrade -y
|
||||
apt-get install -y pkg-config liblzma-dev
|
||||
- uses: actions/checkout@v4
|
||||
- run: cabal update
|
||||
- run: cabal build
|
||||
- name: Archive
|
||||
run: |
|
||||
DISTRIBUTION=$(echo $GITHUB_REF_NAME | awk '{ gsub(/^v/, "slackbuilder-"); print $0 }')
|
||||
cabal install --installdir=$DISTRIBUTION/bin --install-method=copy
|
||||
strip $DISTRIBUTION/bin/slackbuilder
|
||||
tar Jcvf $DISTRIBUTION.tar.xz $DISTRIBUTION
|
||||
- uses: akkuman/gitea-release-action@v1
|
||||
with:
|
||||
files: "*.tar.xz"
|
||||
token: ${{ secrets.API_KEY }}
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -14,15 +14,15 @@
|
||||
*.lz
|
||||
*.pk3
|
||||
*.run
|
||||
*.Z
|
||||
*.deb
|
||||
*.jar
|
||||
*~
|
||||
.directory
|
||||
*.phar
|
||||
|
||||
/slackbuilds/
|
||||
/config/config.toml
|
||||
/config/config.rb
|
||||
/vendor/
|
||||
/.bundle/
|
||||
/pkg/
|
||||
/dist-newstyle/
|
||||
|
2
.hlint.yaml
Normal file
2
.hlint.yaml
Normal file
@ -0,0 +1,2 @@
|
||||
arguments:
|
||||
- -XQuasiQuotes
|
41
.rubocop.yml
41
.rubocop.yml
@ -1,41 +0,0 @@
|
||||
AllCops:
|
||||
Exclude:
|
||||
- 'vendor/**/*'
|
||||
- '.git/**/*'
|
||||
- 'slackbuilds/**/*'
|
||||
- 'bin/bundle'
|
||||
- 'bin/cap*'
|
||||
- 'bin/rake'
|
||||
- 'bin/rspec'
|
||||
- 'bin/rubocop'
|
||||
- 'bin/setup'
|
||||
- 'bin/spring'
|
||||
- 'bin/update'
|
||||
- 'pkg/**/*'
|
||||
|
||||
TargetRubyVersion: '3.0'
|
||||
NewCops: enable
|
||||
SuggestExtensions: false
|
||||
|
||||
Style/Documentation:
|
||||
Enabled: false
|
||||
|
||||
# False-Positive: non-string-variable + 'some string'
|
||||
Style/StringConcatenation:
|
||||
Enabled: false
|
||||
|
||||
Layout/MultilineMethodCallIndentation:
|
||||
EnforcedStyle: indented
|
||||
|
||||
Layout/MultilineOperationIndentation:
|
||||
EnforcedStyle: indented
|
||||
|
||||
Layout/ArgumentAlignment:
|
||||
EnforcedStyle: with_fixed_indentation
|
||||
|
||||
Layout/EndAlignment:
|
||||
EnforcedStyleAlignWith: variable
|
||||
|
||||
Metrics/BlockLength:
|
||||
AllowedMethods:
|
||||
- namespace
|
5
CHANGELOG.md
Normal file
5
CHANGELOG.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Revision history for slackbuilder
|
||||
|
||||
## 0.1.0.0 -- YYYY-mm-dd
|
||||
|
||||
* First version. Released on an unsuspecting world.
|
15
Gemfile
15
Gemfile
@ -1,15 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
# frozen_string_literal: true
|
||||
|
||||
source 'https://rubygems.org'
|
||||
|
||||
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
||||
|
||||
gem 'rake', '~> 13.0'
|
||||
gem 'rubocop', '~> 1.7', require: false
|
||||
|
||||
gem 'progressbar', '~> 1.11'
|
||||
gem 'term-ansicolor', '~> 1.7'
|
44
Gemfile.lock
44
Gemfile.lock
@ -1,44 +0,0 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
ast (2.4.2)
|
||||
json (2.6.2)
|
||||
parallel (1.22.1)
|
||||
parser (3.1.2.1)
|
||||
ast (~> 2.4.1)
|
||||
progressbar (1.11.0)
|
||||
rainbow (3.1.1)
|
||||
rake (13.0.6)
|
||||
regexp_parser (2.6.0)
|
||||
rexml (3.2.5)
|
||||
rubocop (1.38.0)
|
||||
json (~> 2.3)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 3.1.2.1)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
regexp_parser (>= 1.8, < 3.0)
|
||||
rexml (>= 3.2.5, < 4.0)
|
||||
rubocop-ast (>= 1.23.0, < 2.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 1.4.0, < 3.0)
|
||||
rubocop-ast (1.23.0)
|
||||
parser (>= 3.1.1.0)
|
||||
ruby-progressbar (1.11.0)
|
||||
sync (0.5.0)
|
||||
term-ansicolor (1.7.1)
|
||||
tins (~> 1.0)
|
||||
tins (1.32.1)
|
||||
sync
|
||||
unicode-display_width (2.3.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
progressbar (~> 1.11)
|
||||
rake (~> 13.0)
|
||||
rubocop (~> 1.7)
|
||||
term-ansicolor (~> 1.7)
|
||||
|
||||
BUNDLED WITH
|
||||
2.2.33
|
79
README.md
Normal file
79
README.md
Normal file
@ -0,0 +1,79 @@
|
||||
# SlackBuilder
|
||||
|
||||
SlackBuilder is a tool which aims to help to update Slackware packages.
|
||||
It checks for the latest version of an upstream package and can modify
|
||||
SlackBuild meta information accordingly.
|
||||
|
||||
## Features
|
||||
|
||||
- Querying various sources (like registries) for the latest upstream version.
|
||||
Currently supported sources are:
|
||||
- GitHub
|
||||
- Packagist
|
||||
- Remote text file containing a version number (like the LATEST file).
|
||||
- Updating package version and checksum in the .info file;
|
||||
Updating version variables in the .SlackBuild
|
||||
- Updating packages with multiple sources. One source is assumed to be the main
|
||||
source and match the version of the package. Other sources are just updated to
|
||||
the latest version available for them.
|
||||
- Modifying or just reuploading source tarballs to a different destination.
|
||||
SlackBuilder can download the original source tarball, optionally extract and
|
||||
modify its contents, and upload it to another server. It can be used for
|
||||
example to download package dependencies to ship them all within a single
|
||||
archive, so the package can be built offline.
|
||||
|
||||
## Build instructions
|
||||
|
||||
SlackBuilder is a Haskell program and can be built and run using the
|
||||
Cabal build tool and package manager:
|
||||
|
||||
```sh
|
||||
cabal build
|
||||
```
|
||||
|
||||
After that you can run slackbuilder using Cabal and `cabal run slackbuilder`.
|
||||
Or you can install the program locally with `cabal install` and run it just
|
||||
as `slackbuilder` assuming `~/.cabal/bin` is on your PATH.
|
||||
|
||||
# Usage
|
||||
|
||||
## Configuration
|
||||
|
||||
There is a sample configuration file under `config/config.toml.example`.
|
||||
The sample contains comments describing each supported option.
|
||||
Just copy this file to `config/config.toml` and modify as needed.
|
||||
|
||||
Each package that should be updated automatically needs a special
|
||||
description which contains links to the upstream repositories and
|
||||
instructions how the sources should be prepared.
|
||||
|
||||
Unfortunately the only format currently supported for the package
|
||||
descriptions is Haskell source code. But I'm planning to make it
|
||||
possible to describe the packages without recompiling the slackbuilder
|
||||
itself.
|
||||
|
||||
For the time being `src/Main.hs` contains descriptions of my
|
||||
slackbuilds, that can be used as an example and a start point.
|
||||
|
||||
## Command line options
|
||||
|
||||
SlackBuilder is called with a command as its first argument:
|
||||
|
||||
```sh
|
||||
slackbuilder COMMAND
|
||||
```
|
||||
|
||||
Currently supported commands are listed below.
|
||||
|
||||
### check
|
||||
|
||||
`check` checks whether there are updates available. It prints the name of each
|
||||
known package together with its version. If the package version is not the
|
||||
latest known version, the version the package can be updated to is printed as
|
||||
well.
|
||||
|
||||
### up2date
|
||||
|
||||
Performs the package updates for packages the can be updated. `up2date` accepts
|
||||
an optional argument specifying the package that should be updated if only one
|
||||
package should be updated and not all.
|
107
Rakefile
107
Rakefile
@ -1,107 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'digest/md5'
|
||||
require 'net/http'
|
||||
require_relative 'config/config'
|
||||
require_relative 'lib/package'
|
||||
require_relative 'lib/download'
|
||||
|
||||
task :dmd, [:version] do |_, arguments|
|
||||
raise 'Version is not specified.' unless arguments.key? :version
|
||||
|
||||
dub_version = '1.30.0'
|
||||
dscanner_version = '0.12.2'
|
||||
dcd_version = '0.13.6'
|
||||
|
||||
SlackBuilder::DmdTools.update_dmd arguments[:version]
|
||||
SlackBuilder::DmdTools.update_tools arguments[:version], dub_version, dscanner_version, dcd_version
|
||||
end
|
||||
|
||||
task :composer, [:version] do |_, arguments|
|
||||
raise 'Version is not specified.' unless arguments.key? :version
|
||||
|
||||
package = Package.new 'development/composer',
|
||||
version: arguments[:version],
|
||||
homepage: 'https://getcomposer.org/'
|
||||
|
||||
uri = "https://getcomposer.org/download/#{arguments[:version]}/composer.phar"
|
||||
checksum = download URI(uri), 'slackbuilds/development/composer/composer.phar'
|
||||
write_info package, downloads: [Download.new(uri, checksum.hexdigest)]
|
||||
update_slackbuild_version 'development/composer', arguments[:version]
|
||||
|
||||
commit 'development/composer', arguments[:version]
|
||||
end
|
||||
|
||||
task 'universal-ctags', [:version] do |_, arguments|
|
||||
raise 'Version is not specified.' unless arguments.key? :version
|
||||
|
||||
package = Package.new 'development/universal-ctags',
|
||||
version: arguments[:version],
|
||||
homepage: 'https://ctags.io/',
|
||||
requires: ['%README%']
|
||||
|
||||
uri = "https://github.com/universal-ctags/ctags/archive/#{arguments[:version]}/ctags-#{arguments[:version]}.tar.gz"
|
||||
tarball = "slackbuilds/development/universal-ctags/ctags-#{arguments[:version]}.tar.gz"
|
||||
checksum = download URI(uri), tarball
|
||||
download = "https://download.dlackware.com/hosted-sources/universal-ctags/ctags-#{arguments[:version]}.tar.gz"
|
||||
|
||||
write_info package,
|
||||
downloads: [Download.new(download, checksum.hexdigest)]
|
||||
update_slackbuild_version 'development/universal-ctags', arguments[:version]
|
||||
sh 'scp', tarball, "#{CONFIG[:remote_path]}/universal-ctags"
|
||||
|
||||
commit 'development/universal-ctags', arguments[:version]
|
||||
end
|
||||
|
||||
task :hhvm do
|
||||
raise 'Version is not specified.' unless arguments.key? :version
|
||||
|
||||
checksum = {}
|
||||
checksum[:hhvm] = clone 'https://github.com/facebook/hhvm.git',
|
||||
"development/hhvm/hhvm-#{arguments[:version]}.tar.xz", 'HHVM-'
|
||||
|
||||
package = Package.new 'development/hhvm',
|
||||
version: arguments[:version],
|
||||
homepage: 'https://hhvm.com/',
|
||||
requires: %w[tbb glog libdwarf libmemcached dobule-conversion]
|
||||
|
||||
write_info package,
|
||||
downloads: [
|
||||
Download.new(hosted_sources("/hhvm/hhvm-#{package.version}.tar.xz"), checksum[:hhvm], is64: true)
|
||||
]
|
||||
|
||||
update_slackbuild_version 'development/hhvm', package.version
|
||||
end
|
||||
|
||||
task :ioncube do
|
||||
raise 'Version is not specified.' unless arguments.key? :version
|
||||
|
||||
tarball_name = {
|
||||
'32' => "ioncube_loaders_lin_x86_#{arguments[:version]}.tar.gz",
|
||||
'64' => "ioncube_loaders_lin_x86-64_#{arguments[:version]}.tar.gz"
|
||||
}
|
||||
uri = {
|
||||
'32' => URI("http://downloads3.ioncube.com/loader_downloads/#{tarball_name['32']}"),
|
||||
'64' => URI("http://downloads3.ioncube.com/loader_downloads/#{tarball_name['64']}")
|
||||
}
|
||||
checksum = {
|
||||
'32' => download(uri['32'], "slackbuilds/development/ioncube-loader/#{tarball_name['32']}").hexdigest,
|
||||
'64' => download(uri['64'], "slackbuilds/development/ioncube-loader/#{tarball_name['64']}").hexdigest
|
||||
}
|
||||
package = Package.new 'development/ioncube-loader',
|
||||
version: arguments[:version],
|
||||
homepage: 'https://www.ioncube.com'
|
||||
|
||||
write_info package,
|
||||
downloads: [
|
||||
Download.new(uri['32'], checksum['32']),
|
||||
Download.new(uri['64'], checksum['64'], is64: true)
|
||||
]
|
||||
|
||||
update_slackbuild_version 'development/ioncube-loader', package.version
|
||||
commit 'development/ioncube-loader', package.version
|
||||
end
|
29
bin/rubocop
29
bin/rubocop
@ -1,29 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'rubocop' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require "pathname"
|
||||
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
||||
|
||||
if File.file?(bundle_binstub)
|
||||
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
||||
load(bundle_binstub)
|
||||
else
|
||||
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
||||
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
||||
end
|
||||
end
|
||||
|
||||
require "rubygems"
|
||||
require "bundler/setup"
|
||||
|
||||
load Gem.bin_path("rubocop", "rubocop")
|
@ -1,7 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
CONFIG = {
|
||||
remote_path: 'example.com:/srv/httpd/some/path',
|
||||
download_url: 'https://example.com/some/path',
|
||||
branch: 'user/nick/updates'
|
||||
}.freeze
|
35
config/config.toml.example
Normal file
35
config/config.toml.example
Normal file
@ -0,0 +1,35 @@
|
||||
## Global options
|
||||
|
||||
# Accessing GitHub APIs is only possible using a personal access token. The
|
||||
# token doesn't need any scopes set since it is used to query public
|
||||
# repositories.
|
||||
gh_token = ""
|
||||
|
||||
# Relative path to a cloned SBo repository.
|
||||
repository = "./slackbuilds"
|
||||
|
||||
# After one package is updated a commit is created on this branch. The branch is
|
||||
# not pushed or reset automatically.
|
||||
branch = "user/nick/updates"
|
||||
|
||||
# If some packages use custom sources and these sources a generated during the
|
||||
# update, this option specifies the base URL where the sources can be downloaded
|
||||
# afterwads. The full URL written into the .info file contains download_url,
|
||||
# followed by the package name and source file name. This option should probably
|
||||
# be configured consistently with the remote_path.
|
||||
download_url = "https://example.com/some/path"
|
||||
|
||||
# If a package updater generates a source tarball, the tarball is uploaded with
|
||||
# a command given in this parameter. The parameter is a array where the first
|
||||
# element is the command with the following elements being the command
|
||||
# arguments. The command supports 2 placeholders:
|
||||
# %s - Path to the source archive.
|
||||
# %c - Package category.
|
||||
upload_command = ["scp", "%s", "example.com:/srv/httpd/some/path/%c"]
|
||||
|
||||
## Maintainer specific options
|
||||
[maintainer]
|
||||
|
||||
# Whether the git commits should be signed with a GPG signature using the
|
||||
# default key.
|
||||
signature = false
|
95
lib/SlackBuilder/Config.hs
Normal file
95
lib/SlackBuilder/Config.hs
Normal file
@ -0,0 +1,95 @@
|
||||
{- This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||
v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
obtain one at https://mozilla.org/MPL/2.0/. -}
|
||||
|
||||
-- | Configuration file.
|
||||
module SlackBuilder.Config
|
||||
( CloneSettings(..)
|
||||
, DownloaderSettings(..)
|
||||
, Settings(..)
|
||||
, MaintainerSettings(..)
|
||||
, PackageSettings(..)
|
||||
, settingsCodec
|
||||
) where
|
||||
|
||||
import Data.List.NonEmpty (NonEmpty(..))
|
||||
import Data.Text (Text)
|
||||
import Toml ((.=))
|
||||
import qualified Toml
|
||||
import GHC.Records (HasField(..))
|
||||
|
||||
data Settings = Settings
|
||||
{ ghToken :: !Text
|
||||
, repository :: !FilePath
|
||||
, branch :: Text
|
||||
, downloadURL :: Text
|
||||
, uploadCommand :: NonEmpty Text
|
||||
, maintainer :: MaintainerSettings
|
||||
, packages :: [PackageSettings]
|
||||
} deriving (Eq, Show)
|
||||
|
||||
newtype MaintainerSettings = MaintainerSettings
|
||||
{ signature :: Bool
|
||||
} deriving (Eq, Show)
|
||||
|
||||
data DownloaderSettings = DownloaderSettings
|
||||
{ name :: Text
|
||||
, is64 :: Bool
|
||||
, version :: Text
|
||||
, template :: Maybe Text
|
||||
, clone :: Maybe CloneSettings
|
||||
, github :: Maybe (Text, Text)
|
||||
, packagist :: Maybe (Text, Text)
|
||||
, text :: Maybe (Text, [String])
|
||||
, repackage :: Maybe [String]
|
||||
} deriving (Eq, Show)
|
||||
|
||||
data PackageSettings = PackageSettings
|
||||
{ downloader :: DownloaderSettings
|
||||
, downloaders :: [DownloaderSettings]
|
||||
} deriving (Eq, Show)
|
||||
|
||||
data CloneSettings = CloneSettings
|
||||
{ remote :: Text
|
||||
, tagTemplate :: Text
|
||||
} deriving (Eq, Show)
|
||||
|
||||
settingsCodec :: Toml.TomlCodec Settings
|
||||
settingsCodec = Settings
|
||||
<$> Toml.text "gh_token" .= ghToken
|
||||
<*> Toml.string "repository" .= repository
|
||||
<*> Toml.text "branch" .= branch
|
||||
<*> Toml.text "download_url" .= downloadURL
|
||||
<*> Toml.arrayNonEmptyOf Toml._Text "upload_command" .= uploadCommand
|
||||
<*> Toml.table maintainerSettingsCodec "maintainer" .= maintainer
|
||||
<*> Toml.list packageSettingsCodec "package" .= packages
|
||||
|
||||
maintainerSettingsCodec :: Toml.TomlCodec MaintainerSettings
|
||||
maintainerSettingsCodec = MaintainerSettings
|
||||
<$> Toml.bool "signature" .= signature
|
||||
|
||||
downloaderSettingsCodec :: Toml.TomlCodec DownloaderSettings
|
||||
downloaderSettingsCodec = DownloaderSettings
|
||||
<$> Toml.text "name" .= name
|
||||
<*> Toml.bool "is64" .= is64
|
||||
<*> Toml.text "version" .= version
|
||||
<*> Toml.dioptional (Toml.text "template") .= template
|
||||
<*> Toml.dioptional (Toml.table cloneSettingsCodec "clone") .= clone
|
||||
<*> Toml.dioptional (Toml.table githubCodec "github") .= github
|
||||
<*> Toml.dioptional (Toml.table packagistCodec "packagist") .= packagist
|
||||
<*> Toml.dioptional (Toml.table textCodec "text") .= text
|
||||
<*> Toml.dioptional (Toml.arrayOf Toml._String "repackage") .= repackage
|
||||
where
|
||||
githubCodec = Toml.pair (Toml.text "owner") (Toml.text "name")
|
||||
packagistCodec = Toml.pair (Toml.text "owner") (Toml.text "name")
|
||||
textCodec = Toml.pair (Toml.text "url") (Toml.arrayOf Toml._String "picker")
|
||||
|
||||
packageSettingsCodec :: Toml.TomlCodec PackageSettings
|
||||
packageSettingsCodec = PackageSettings
|
||||
<$> downloaderSettingsCodec .= getField @"downloader"
|
||||
<*> Toml.list downloaderSettingsCodec "downloader" .= downloaders
|
||||
|
||||
cloneSettingsCodec :: Toml.TomlCodec CloneSettings
|
||||
cloneSettingsCodec = CloneSettings
|
||||
<$> Toml.text "remote" .= remote
|
||||
<*> Toml.text "tag_template" .= tagTemplate
|
360
lib/SlackBuilder/Download.hs
Normal file
360
lib/SlackBuilder/Download.hs
Normal file
@ -0,0 +1,360 @@
|
||||
{- This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||
v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
obtain one at https://mozilla.org/MPL/2.0/. -}
|
||||
|
||||
-- | Contains routines for downloading, cloning and uploading sources.
|
||||
module SlackBuilder.Download
|
||||
( cloneAndUpload
|
||||
, extractRemote
|
||||
, commit
|
||||
, createLzmaTarball
|
||||
, download
|
||||
, hostedSources
|
||||
, remoteFileExists
|
||||
, responseBodySource
|
||||
, reqGet
|
||||
, sinkFileAndHash
|
||||
, sinkHash
|
||||
, updateSlackBuildVersion
|
||||
, uploadSource
|
||||
) where
|
||||
|
||||
import qualified Codec.Compression.Lzma as Lzma
|
||||
import Data.ByteString (ByteString)
|
||||
import qualified Data.ByteString as ByteString
|
||||
import qualified Data.ByteString.Char8 as Char8
|
||||
import Data.List.NonEmpty (NonEmpty(..))
|
||||
import qualified Data.List.NonEmpty as NonEmpty
|
||||
import Data.NonNull (toNullable)
|
||||
import Data.Foldable (find)
|
||||
import Data.Map.Strict (Map)
|
||||
import qualified Data.Map.Strict as Map
|
||||
import Data.Text (Text)
|
||||
import qualified Data.Text as Text
|
||||
import qualified Data.Text.IO as Text.IO
|
||||
import SlackBuilder.Config
|
||||
import SlackBuilder.Trans
|
||||
import Control.Monad.Trans.Reader (asks)
|
||||
import Control.Monad.IO.Class (MonadIO(liftIO))
|
||||
import System.Directory (createDirectory, removePathForcibly)
|
||||
import System.IO (IOMode(..), withFile)
|
||||
import System.FilePath ((</>), (<.>), takeFileName, takeDirectory, stripExtension)
|
||||
import System.Process
|
||||
( CreateProcess(..)
|
||||
, StdStream(..)
|
||||
, proc
|
||||
, readCreateProcessWithExitCode
|
||||
, callProcess
|
||||
)
|
||||
import System.Exit (ExitCode(..))
|
||||
import Control.Monad (unless, void)
|
||||
import Text.URI (URI(..))
|
||||
import qualified Text.URI as URI
|
||||
import Network.HTTP.Req
|
||||
( useHttpsURI
|
||||
, useURI
|
||||
, HEAD(..)
|
||||
, NoReqBody(..)
|
||||
, req
|
||||
, runReq
|
||||
, defaultHttpConfig
|
||||
, ignoreResponse
|
||||
, responseStatusCode
|
||||
, MonadHttp
|
||||
, HttpConfig(..)
|
||||
, GET(..)
|
||||
, reqBr
|
||||
)
|
||||
import Data.Functor ((<&>))
|
||||
import Network.HTTP.Client (BodyReader, Response(..), brRead)
|
||||
import Conduit
|
||||
( ConduitT
|
||||
, MonadResource
|
||||
, yield
|
||||
, runConduitRes
|
||||
, sinkFile
|
||||
, (.|)
|
||||
, ZipSink(..)
|
||||
, await
|
||||
, sourceFile
|
||||
, leftover
|
||||
, awaitNonNull
|
||||
)
|
||||
import Data.Conduit.Tar (FileInfo(..), tarFilePath, untar)
|
||||
import Crypto.Hash (Digest, MD5, hashInit, hashFinalize, hashUpdate)
|
||||
import Data.Void (Void)
|
||||
import qualified Data.Conduit.Zlib as Zlib
|
||||
import Control.Monad.Catch (MonadThrow(..))
|
||||
import Data.Maybe (fromMaybe)
|
||||
|
||||
updateSlackBuildVersion :: Text -> Text -> Map Text Text -> SlackBuilderT ()
|
||||
updateSlackBuildVersion packagePath version additionalDownloads = do
|
||||
repository' <- SlackBuilderT $ asks repository
|
||||
let name = Text.unpack $ snd $ Text.breakOnEnd "/" packagePath
|
||||
slackbuildFilename = repository'
|
||||
</> Text.unpack packagePath
|
||||
</> (name <.> "SlackBuild")
|
||||
slackbuildContents <- liftIO $ Text.IO.readFile slackbuildFilename
|
||||
let slackbuildLines = replaceLine . updateLineVariable "VERSION" version
|
||||
<$> Text.lines slackbuildContents
|
||||
|
||||
liftIO $ Text.IO.writeFile slackbuildFilename $ Text.unlines slackbuildLines
|
||||
where
|
||||
replaceLine line = Map.foldrWithKey updateLineDependencyVersion line additionalDownloads
|
||||
updateLineDependencyVersion dependencyName = updateLineVariable
|
||||
$ dependencyName <> "_VERSION"
|
||||
updateLineVariable variableName variableValue line
|
||||
| Text.isPrefixOf (variableName <> "=") line =
|
||||
variableName <> "=${" <> variableName <> ":-" <> variableValue <> "}"
|
||||
| otherwise = line
|
||||
|
||||
commit :: Text -> Text -> SlackBuilderT ()
|
||||
commit packagePath version = do
|
||||
branch' <- SlackBuilderT $ Text.unpack <$> asks branch
|
||||
repository' <- SlackBuilderT $ asks repository
|
||||
signature' <- SlackBuilderT $ asks $ signature . maintainer
|
||||
let message = Text.unpack
|
||||
$ packagePath <> ": Updated for version " <> version
|
||||
mainCommitArguments = ["-C", repository', "commit", "-m", message]
|
||||
commitArguments =
|
||||
if signature'
|
||||
then mainCommitArguments <> ["-S"]
|
||||
else mainCommitArguments
|
||||
|
||||
(checkoutExitCode, _, _) <- liftIO
|
||||
$ withFile "/dev/null" WriteMode
|
||||
$ testCheckout repository' branch'
|
||||
|
||||
unless (checkoutExitCode == ExitSuccess)
|
||||
$ liftIO
|
||||
$ callProcess "git" ["-C", repository', "checkout", "-b", branch', "master"]
|
||||
liftIO
|
||||
$ callProcess "git" ["-C", repository', "add", Text.unpack packagePath]
|
||||
>> callProcess "git" commitArguments
|
||||
where
|
||||
testCheckout repository' branch' nullHandle =
|
||||
let createCheckoutProcess = (proc "git" ["-C", repository', "checkout", branch'])
|
||||
{ std_in = NoStream
|
||||
, std_err = UseHandle nullHandle
|
||||
}
|
||||
in readCreateProcessWithExitCode createCheckoutProcess ""
|
||||
|
||||
hostedSources :: NonEmpty Text -> SlackBuilderT URI
|
||||
hostedSources urlPathPieces = do
|
||||
downloadURL' <- SlackBuilderT (asks downloadURL) >>= URI.mkURI
|
||||
urlPathPieces' <- traverse URI.mkPathPiece urlPathPieces
|
||||
|
||||
let updatedPath = case URI.uriPath downloadURL' of
|
||||
Just (_, existingPath) ->
|
||||
NonEmpty.append existingPath urlPathPieces'
|
||||
Nothing -> urlPathPieces'
|
||||
pure $ downloadURL'{ uriPath = Just (False, updatedPath) }
|
||||
|
||||
remoteFileExists :: NonEmpty Text -> SlackBuilderT Bool
|
||||
remoteFileExists urlPathPieces = hostedSources urlPathPieces
|
||||
>>= traverse (runReq httpConfig . go . fst) . useHttpsURI
|
||||
<&> maybe False ((== 200) . responseStatusCode)
|
||||
where
|
||||
httpConfig = defaultHttpConfig
|
||||
{ httpConfigCheckResponse = const $ const $ const Nothing
|
||||
}
|
||||
go uri = req HEAD uri NoReqBody ignoreResponse mempty
|
||||
|
||||
cloneAndArchive :: Text -> FilePath -> Text -> SlackBuilderT ()
|
||||
cloneAndArchive repo tarballPath tagPrefix = do
|
||||
let version = snd $ Text.breakOnEnd "-"
|
||||
$ Text.pack $ takeFileName tarballPath
|
||||
|
||||
repositoryTarballPath <- relativeToRepository tarballPath
|
||||
repositoryArchivePath <- relativeToRepository $ tarballPath <.> "tar.xz"
|
||||
liftIO
|
||||
$ removePathForcibly repositoryTarballPath
|
||||
>> callProcess "git"
|
||||
[ "clone"
|
||||
, Text.unpack repo
|
||||
, repositoryTarballPath
|
||||
]
|
||||
>> callProcess "git"
|
||||
[ "-C"
|
||||
, repositoryTarballPath
|
||||
, "checkout"
|
||||
, Text.unpack $ tagPrefix <> version
|
||||
]
|
||||
>> callProcess "git"
|
||||
[ "-C"
|
||||
, repositoryTarballPath
|
||||
, "submodule"
|
||||
, "update"
|
||||
, "--init"
|
||||
, "--recursive"
|
||||
]
|
||||
>> createLzmaTarball repositoryTarballPath repositoryArchivePath
|
||||
>> removePathForcibly repositoryTarballPath
|
||||
|
||||
-- | Takes a directory as input and a file name as output and creates a tar.xz
|
||||
-- archive from the given directory.
|
||||
createLzmaTarball :: FilePath -> FilePath -> IO (Digest MD5)
|
||||
createLzmaTarball input output = runConduitRes $ yield input
|
||||
.| void tarFilePath
|
||||
.| compressLzma
|
||||
.| sinkFileAndHash output
|
||||
|
||||
responseBodySource :: MonadIO m => Response BodyReader -> ConduitT i ByteString m ()
|
||||
responseBodySource = bodyReaderSource . responseBody
|
||||
where
|
||||
bodyReaderSource br = liftIO (brRead br) >>= go br
|
||||
go br bs = unless (ByteString.null bs) $ yield bs >> bodyReaderSource br
|
||||
|
||||
sinkHash :: Monad m => ConduitT ByteString Void m (Digest MD5)
|
||||
sinkHash = sink hashInit
|
||||
where
|
||||
sink ctx = await
|
||||
>>= maybe (pure $ hashFinalize ctx) (sink . hashUpdate ctx)
|
||||
|
||||
cloneAndUpload :: Text -> FilePath -> Text -> SlackBuilderT (URI, Digest MD5)
|
||||
cloneAndUpload repo tarballPath tagPrefix = do
|
||||
let tarballFileName = takeFileName tarballPath <.> "tar.xz"
|
||||
packageName = takeFileName $ takeDirectory tarballPath
|
||||
remoteArchivePath = Text.pack $ packageName </> tarballFileName
|
||||
urlPathPieces = Text.pack <$> packageName :| [tarballFileName]
|
||||
|
||||
localPath <- relativeToRepository tarballFileName
|
||||
remoteResultURI <- hostedSources urlPathPieces
|
||||
remoteFileExists' <- remoteFileExists urlPathPieces
|
||||
|
||||
if remoteFileExists'
|
||||
then (remoteResultURI,) . snd
|
||||
<$> download remoteResultURI (takeDirectory localPath)
|
||||
else
|
||||
let go = sourceFile localPath .| sinkHash
|
||||
in cloneAndArchive repo tarballPath tagPrefix
|
||||
>> uploadSource localPath remoteArchivePath
|
||||
>> liftIO (runConduitRes go) <&> (remoteResultURI,)
|
||||
|
||||
-- | Given a path to a local file and a remote path uploads the file using
|
||||
-- the settings given in the configuration file.
|
||||
--
|
||||
-- The remote path is given relative to the path in the configuration.
|
||||
uploadSource :: FilePath -> Text -> SlackBuilderT ()
|
||||
uploadSource localPath remotePath' = do
|
||||
uploadCommand' :| uploadArguments <- SlackBuilderT $ asks uploadCommand
|
||||
let uploadArguments' = Text.unpack
|
||||
. Text.replace "%s" (Text.pack localPath)
|
||||
. Text.replace "%c" remotePath'
|
||||
<$> uploadArguments
|
||||
|
||||
liftIO $ callProcess (Text.unpack uploadCommand') uploadArguments'
|
||||
|
||||
-- | Downlaods a file into the directory. Returns name of the downloaded file
|
||||
-- and checksum.
|
||||
--
|
||||
-- The filename is read from the disposition header or from the URL if the
|
||||
-- Content-Disposition is missing.
|
||||
download :: URI -> FilePath -> SlackBuilderT (FilePath, Digest MD5)
|
||||
download uri packagePath = runReq defaultHttpConfig go
|
||||
where
|
||||
go
|
||||
| Just uriPath <- URI.uriPath uri =
|
||||
reqGet uri
|
||||
$ readResponse
|
||||
$ Text.unpack
|
||||
$ URI.unRText
|
||||
$ NonEmpty.last
|
||||
$ snd uriPath
|
||||
| otherwise = throwM $ UnsupportedUrlType uri
|
||||
readResponse :: FilePath -> Response BodyReader -> IO (FilePath, Digest MD5)
|
||||
readResponse downloadFileName response = do
|
||||
let attachmentName = dispositionAttachment response
|
||||
targetFileName = fromMaybe downloadFileName attachmentName
|
||||
target = packagePath </> fromMaybe downloadFileName attachmentName
|
||||
digest <- runConduitRes
|
||||
$ responseBodySource response
|
||||
.| sinkFileAndHash target
|
||||
pure (targetFileName, digest)
|
||||
|
||||
-- | Writes a file to the destination path and accumulates its MD5 checksum.
|
||||
sinkFileAndHash :: MonadResource m => FilePath -> ConduitT ByteString Void m (Digest MD5)
|
||||
sinkFileAndHash target = getZipSink
|
||||
$ ZipSink (sinkFile target) *> ZipSink sinkHash
|
||||
|
||||
compressLzma :: MonadIO m => ConduitT ByteString ByteString m ()
|
||||
compressLzma = liftIO (Lzma.compressIO Lzma.defaultCompressParams) >>= go
|
||||
where
|
||||
go (Lzma.CompressInputRequired flush supplyInput) = do
|
||||
next <- await
|
||||
result <- case next of
|
||||
Just input
|
||||
| ByteString.null input -> liftIO flush
|
||||
| otherwise -> liftIO $ supplyInput input
|
||||
Nothing -> liftIO $ supplyInput mempty
|
||||
go result
|
||||
go (Lzma.CompressOutputAvailable output stream) = yield output
|
||||
>> liftIO stream >>= go
|
||||
go Lzma.CompressStreamEnd = pure ()
|
||||
|
||||
decompressLzma :: (MonadThrow m, MonadIO m) => ConduitT ByteString ByteString m ()
|
||||
decompressLzma = liftIO (Lzma.decompressIO Lzma.defaultDecompressParams) >>= go
|
||||
where
|
||||
go (Lzma.DecompressInputRequired processor) = do
|
||||
next <- awaitNonNull
|
||||
result <- case next of
|
||||
Just input -> liftIO $ processor (toNullable input)
|
||||
Nothing -> liftIO $ processor mempty
|
||||
go result
|
||||
go (Lzma.DecompressOutputAvailable output stream) = yield output
|
||||
>> liftIO stream
|
||||
>>= go
|
||||
go (Lzma.DecompressStreamEnd output) = leftover output
|
||||
go (Lzma.DecompressStreamError lzmaReturn) = throwM
|
||||
$ LzmaDecompressionFailed lzmaReturn
|
||||
|
||||
-- | Downloads a compressed tar archive and extracts its contents on the fly to
|
||||
-- a directory.
|
||||
--
|
||||
-- If the download contains the disposition header and the attachment type was
|
||||
-- recognized as tar archive, returns the attachment name from the
|
||||
-- disposition header without the extension. So if the disposition header
|
||||
-- is "attachment; filename=package-1.2.3.tar.gz", returns "package-1.2.3".
|
||||
extractRemote :: URI -> FilePath -> SlackBuilderT (Maybe FilePath)
|
||||
extractRemote uri' packagePath =
|
||||
runReq defaultHttpConfig $ go packagePath
|
||||
where
|
||||
go toTarget = reqGet uri' $ readResponse toTarget
|
||||
readResponse :: FilePath -> Response BodyReader -> IO (Maybe FilePath)
|
||||
readResponse toTarget response = do
|
||||
let attachmentName = dispositionAttachment response
|
||||
(decompress, attachmentDirectory) =
|
||||
case attachmentName of
|
||||
Just attachmentName'
|
||||
| Just directoryName' <- stripExtension ".tar.gz" attachmentName' ->
|
||||
(Zlib.ungzip, Just directoryName')
|
||||
| Just directoryName' <- stripExtension ".tar.xz" attachmentName' ->
|
||||
(decompressLzma, Just directoryName')
|
||||
_ -> (pure (), Nothing)
|
||||
runConduitRes $ responseBodySource response
|
||||
.| decompress
|
||||
.| untar (withDecompressedFile toTarget)
|
||||
pure attachmentDirectory
|
||||
withDecompressedFile toTarget FileInfo{..}
|
||||
| Char8.last filePath /= '/' =
|
||||
sinkFile (toTarget </> Char8.unpack filePath)
|
||||
| otherwise = liftIO (createDirectory (toTarget </> Char8.unpack filePath))
|
||||
|
||||
dispositionAttachment :: Response BodyReader -> Maybe FilePath
|
||||
dispositionAttachment response
|
||||
= fmap (Char8.unpack . snd . Char8.breakEnd (== '=') . snd)
|
||||
$ find ((== "Content-Disposition") . fst)
|
||||
$ responseHeaders response
|
||||
|
||||
reqGet :: (MonadThrow m, MonadHttp m)
|
||||
=> URI
|
||||
-> (Response BodyReader -> IO a)
|
||||
-> m a
|
||||
reqGet uri bodyReader =
|
||||
case useURI uri of
|
||||
Just urlWithOptions
|
||||
| Left (httpsURI, httpsOptions) <- urlWithOptions ->
|
||||
reqBr GET httpsURI NoReqBody httpsOptions bodyReader
|
||||
| Right (httpsURI, httpsOptions) <- urlWithOptions ->
|
||||
reqBr GET httpsURI NoReqBody httpsOptions bodyReader
|
||||
_ -> throwM $ UnsupportedUrlType uri
|
166
lib/SlackBuilder/Info.hs
Normal file
166
lib/SlackBuilder/Info.hs
Normal file
@ -0,0 +1,166 @@
|
||||
{- This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||
v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
obtain one at https://mozilla.org/MPL/2.0/. -}
|
||||
|
||||
-- | Info file parsing and printing.
|
||||
module SlackBuilder.Info
|
||||
( PackageInfo(..)
|
||||
, generate
|
||||
, parseInfoFile
|
||||
, readInfoFile
|
||||
) where
|
||||
|
||||
import Control.Applicative (Alternative(..))
|
||||
import Control.Monad.Combinators (sepBy)
|
||||
import qualified Data.ByteArray as ByteArray
|
||||
import Data.ByteString (ByteString)
|
||||
import qualified Data.ByteString as ByteString
|
||||
import qualified Data.ByteString.Char8 as Char8
|
||||
import Data.Maybe (mapMaybe)
|
||||
import Data.Text (Text)
|
||||
import qualified Data.Text as Text
|
||||
import qualified Data.Text.Encoding as Text
|
||||
import qualified Data.Text.Lazy as Lazy.Text
|
||||
import qualified Data.Text.Lazy.Builder as Text.Builder
|
||||
import qualified Data.Text.Lazy.Builder as Text (Builder)
|
||||
import Crypto.Hash (Digest, MD5, digestFromByteString)
|
||||
import Data.Void (Void)
|
||||
import Data.Word (Word8)
|
||||
import Numeric (readHex, showHex)
|
||||
import Text.Megaparsec (Parsec, count, eof, parse, takeWhile1P)
|
||||
import Text.Megaparsec.Byte (hspace1, space, string, hexDigitChar)
|
||||
import Text.URI
|
||||
( URI(..)
|
||||
, parserBs
|
||||
, render
|
||||
)
|
||||
import qualified Data.Word8 as Word8
|
||||
import SlackBuilder.Trans
|
||||
( SlackBuilderT(..)
|
||||
, SlackBuilderException(..)
|
||||
, relativeToRepository
|
||||
)
|
||||
import System.FilePath ((</>), (<.>))
|
||||
import Control.Monad.IO.Class (MonadIO(..))
|
||||
import Conduit (MonadThrow(throwM))
|
||||
import Control.Monad (void)
|
||||
|
||||
type GenParser = Parsec Void ByteString
|
||||
|
||||
-- | Data used to generate an .info file.
|
||||
data PackageInfo = PackageInfo
|
||||
{ pkgname :: String
|
||||
, version :: Text
|
||||
, homepage :: Text
|
||||
, downloads :: [URI]
|
||||
, checksums :: [Digest MD5]
|
||||
, downloadX64 :: [URI]
|
||||
, checksumX64 :: [Digest MD5]
|
||||
, requires :: [ByteString]
|
||||
, maintainer :: Text
|
||||
, email :: Text
|
||||
} deriving (Eq, Show)
|
||||
|
||||
variableEntry :: ByteString -> GenParser ByteString
|
||||
variableEntry variable = string (Char8.append variable "=\"")
|
||||
*> takeWhile1P Nothing (0x22 /=)
|
||||
<* string "\"\n"
|
||||
|
||||
variableSeparator :: GenParser ()
|
||||
variableSeparator = void $ some $ hspace1 <|> void (string "\\\n")
|
||||
|
||||
packageDownloads :: ByteString -> GenParser [URI]
|
||||
packageDownloads variableName = string (variableName <> "=\"")
|
||||
*> sepBy parserBs variableSeparator
|
||||
<* string "\"\n"
|
||||
|
||||
hexDigit :: GenParser Word8
|
||||
hexDigit = count 2 hexDigitChar
|
||||
>>= extractNumber . readHex . fmap (toEnum . fromIntegral)
|
||||
where
|
||||
extractNumber [(number, "")] = pure number
|
||||
extractNumber _ = fail "Unable to convert a 2-digit hexadecimal number"
|
||||
|
||||
packageChecksum :: GenParser ByteString
|
||||
packageChecksum = ByteString.pack <$> count 16 hexDigit
|
||||
|
||||
packageChecksums :: ByteString -> GenParser [ByteString]
|
||||
packageChecksums variableName = string (variableName <> "=\"")
|
||||
*> sepBy packageChecksum variableSeparator
|
||||
<* string "\"\n"
|
||||
|
||||
packageRequires :: GenParser [ByteString]
|
||||
packageRequires = string "REQUIRES=\""
|
||||
*> sepBy (packageName <|> string "%README%") space
|
||||
<* string "\"\n"
|
||||
|
||||
packageName :: GenParser ByteString
|
||||
packageName = takeWhile1P Nothing isNameToken
|
||||
where
|
||||
isNameToken x = Word8.isAlphaNum x
|
||||
|| x == Word8._hyphen
|
||||
|| x == Word8._underscore
|
||||
|| x == Word8._period
|
||||
|
||||
parseInfoFile :: GenParser PackageInfo
|
||||
parseInfoFile = PackageInfo . Char8.unpack
|
||||
<$> packagePrgnam
|
||||
<*> (Text.decodeUtf8 <$> variableEntry "VERSION")
|
||||
<*> (Text.decodeUtf8 <$> variableEntry "HOMEPAGE")
|
||||
<*> packageDownloads "DOWNLOAD"
|
||||
<*> (mapMaybe digestFromByteString <$> packageChecksums "MD5SUM")
|
||||
<*> packageDownloads "DOWNLOAD_x86_64"
|
||||
<*> (mapMaybe digestFromByteString <$> packageChecksums "MD5SUM_x86_64")
|
||||
<*> packageRequires
|
||||
<*> (Text.decodeUtf8 <$> variableEntry "MAINTAINER")
|
||||
<*> (Text.decodeUtf8 <$> variableEntry "EMAIL")
|
||||
<* eof
|
||||
where
|
||||
packagePrgnam = (string "PKGNAM" <|> string "PRGNAM")
|
||||
>> string "=\""
|
||||
*> packageName
|
||||
<* "\"\n"
|
||||
|
||||
readInfoFile :: Text -> Text -> SlackBuilderT PackageInfo
|
||||
readInfoFile category packageName' = do
|
||||
let packageName'' = Text.unpack packageName'
|
||||
|
||||
infoPath <- relativeToRepository
|
||||
$ Text.unpack category </> packageName'' </> packageName'' <.> "info"
|
||||
infoContents <- liftIO $ ByteString.readFile infoPath
|
||||
|
||||
either (throwM . MalformedInfoFile) pure
|
||||
$ parse parseInfoFile infoPath infoContents
|
||||
|
||||
generate :: PackageInfo -> Text
|
||||
generate pkg = Lazy.Text.toStrict $ Text.Builder.toLazyText builder
|
||||
where
|
||||
digestToText = Text.pack . foldr hexAppender "" . ByteArray.unpack
|
||||
hexAppender x acc
|
||||
| x > 15 = showHex x acc
|
||||
| otherwise = '0' : showHex x acc
|
||||
builder = "PRGNAM=\"" <> Text.Builder.fromString (pkgname pkg) <> "\"\n"
|
||||
<> "VERSION=\"" <> Text.Builder.fromText (version pkg) <> "\"\n"
|
||||
<> "HOMEPAGE=\"" <> Text.Builder.fromText (homepage pkg) <> "\"\n"
|
||||
<> downloadEntry
|
||||
<> generateMultiEntry "MD5SUM" (digestToText <$> checksums pkg)
|
||||
<> generateMultiEntry "DOWNLOAD_x86_64" (render <$> downloadX64 pkg)
|
||||
<> generateMultiEntry "MD5SUM_x86_64" (digestToText <$> checksumX64 pkg)
|
||||
<> "REQUIRES=\"" <> fromByteStringWords (requires pkg) <> "\"\n"
|
||||
<> "MAINTAINER=\"" <> Text.Builder.fromText (maintainer pkg) <> "\"\n"
|
||||
<> "EMAIL=\"" <> Text.Builder.fromText (email pkg) <> "\"\n"
|
||||
fromByteStringWords = Text.Builder.fromText
|
||||
. Text.unwords . fmap Text.decodeUtf8
|
||||
downloadEntry
|
||||
| null $ downloads pkg
|
||||
, not $ null $ downloadX64 pkg = "DOWNLOAD=\"UNSUPPORTED\"\n"
|
||||
| otherwise = generateMultiEntry "DOWNLOAD" $ render <$> downloads pkg
|
||||
|
||||
generateMultiEntry :: Text -> [Text] -> Text.Builder
|
||||
generateMultiEntry name entries = Text.Builder.fromText name
|
||||
<> "=\""
|
||||
<> Text.Builder.fromText (Text.intercalate separator entries)
|
||||
<> "\"\n"
|
||||
where
|
||||
padLength = Text.length name + 2
|
||||
separator = " \\\n" <> Text.replicate padLength " "
|
307
lib/SlackBuilder/LatestVersionCheck.hs
Normal file
307
lib/SlackBuilder/LatestVersionCheck.hs
Normal file
@ -0,0 +1,307 @@
|
||||
{- This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||
v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
obtain one at https://mozilla.org/MPL/2.0/. -}
|
||||
|
||||
-- | This module contains implementations to check the latest version of a
|
||||
-- package hosted by a specific service.
|
||||
module SlackBuilder.LatestVersionCheck
|
||||
( PackageOwner(..)
|
||||
, TextArguments(..)
|
||||
, latestGitHub
|
||||
, latestPackagist
|
||||
, latestText
|
||||
, match
|
||||
) where
|
||||
|
||||
import SlackBuilder.Config
|
||||
import qualified Data.Aeson as Aeson
|
||||
import Data.Aeson ((.:))
|
||||
import Data.Aeson.TH (defaultOptions, deriveJSON)
|
||||
import Data.HashMap.Strict (HashMap)
|
||||
import qualified Data.HashMap.Strict as HashMap
|
||||
import Data.Text (Text)
|
||||
import qualified Data.Text as Text
|
||||
import qualified Data.Text.Encoding as Text.Encoding
|
||||
import Data.Vector (Vector, (!?))
|
||||
import qualified Data.Vector as Vector
|
||||
import Network.HTTP.Req
|
||||
( header
|
||||
, runReq
|
||||
, defaultHttpConfig
|
||||
, req
|
||||
, GET(..)
|
||||
, https
|
||||
, jsonResponse
|
||||
, NoReqBody(..)
|
||||
, (/:)
|
||||
, responseBody
|
||||
, POST(..)
|
||||
, ReqBodyJson(..)
|
||||
, JsonResponse
|
||||
)
|
||||
import Text.URI (mkURI)
|
||||
import SlackBuilder.Trans
|
||||
import qualified Data.Aeson.KeyMap as KeyMap
|
||||
import GHC.Records (HasField(..))
|
||||
import Control.Monad.Trans.Reader (asks)
|
||||
import Data.Char (isAlpha)
|
||||
import SlackBuilder.Download (responseBodySource, reqGet)
|
||||
import Network.HTTP.Client (BodyReader, Response(..))
|
||||
import Conduit (decodeUtf8C, (.|), linesUnboundedC, sinkNull, runConduit)
|
||||
import qualified Data.Conduit.List as CL
|
||||
import Data.Conduit.Process (sourceProcessWithStreams, proc)
|
||||
import Data.Maybe (listToMaybe, mapMaybe)
|
||||
|
||||
data PackageOwner = PackageOwner
|
||||
{ owner :: Text
|
||||
, name :: Text
|
||||
} deriving (Eq, Show)
|
||||
|
||||
data MatchState = MatchState
|
||||
{ ignoring :: !Bool
|
||||
, matched :: !Text
|
||||
, pattern' :: ![MatchToken]
|
||||
} deriving (Eq, Show)
|
||||
|
||||
data MatchToken
|
||||
= OpenParenMatchToken
|
||||
| CloseParenMatchToken
|
||||
| SymbolMatchToken Char
|
||||
| AtLeastMatchToken [Char]
|
||||
| OneOfMatchToken [Char]
|
||||
deriving (Eq, Show)
|
||||
|
||||
-- | Matches a string (for example a version name or CVS tag) against a pattern.
|
||||
-- Returns the matched part of the string or 'Nothing' if there is not match.
|
||||
--
|
||||
-- The pattern is just a list of characters with some special characters and
|
||||
-- sequences.
|
||||
--
|
||||
-- * ( ) - The text in parentheses is matched but no saved in the resulting
|
||||
-- string.
|
||||
-- * \\d - Matches zero or more digits.
|
||||
-- * \\D - Matches one or more digits.
|
||||
-- * \\. - Matches zero or more digits or dots.
|
||||
-- * \\\\ - Matches a back slash.
|
||||
-- * * - Matches everything.
|
||||
-- * [ ] - Match one of the characters inbetween. The characters are
|
||||
-- matched verbatim.
|
||||
--
|
||||
-- For example the following expression matches tags like @v1.2.3@, but returns
|
||||
-- only @1.2.3@.
|
||||
--
|
||||
-- @
|
||||
-- (v)\\.
|
||||
-- @
|
||||
match :: Text -> Text -> Maybe Text
|
||||
match fullPattern = go startState
|
||||
where
|
||||
startState = MatchState
|
||||
{ ignoring = False
|
||||
, matched = mempty
|
||||
, pattern' = parsePattern fullPattern
|
||||
}
|
||||
go :: MatchState -> Text -> Maybe Text
|
||||
-- There is no input, look at the remaining tokens.
|
||||
go MatchState{ pattern' = [], matched } "" = Just matched
|
||||
go state@MatchState{ pattern' = OpenParenMatchToken : tokens } input' =
|
||||
go (state{ ignoring = True, pattern' = tokens }) input'
|
||||
go state@MatchState{ pattern' = CloseParenMatchToken : tokens } input' =
|
||||
go (state{ ignoring = False, pattern' = tokens }) input'
|
||||
go state@MatchState{ pattern' = SymbolMatchToken patternCharacter : tokens } input'
|
||||
| Just (nextCharacter, leftOver) <- Text.uncons input'
|
||||
, patternCharacter == nextCharacter =
|
||||
go (matchSymbolToken state{ pattern' = tokens } nextCharacter) leftOver
|
||||
| otherwise = Nothing
|
||||
go state@MatchState{ pattern' = OneOfMatchToken chars : tokens } input'
|
||||
| Just (nextCharacter, leftOver) <- Text.uncons input'
|
||||
, nextCharacter `elem` chars =
|
||||
go (matchSymbolToken state nextCharacter) leftOver
|
||||
| otherwise =
|
||||
go (state{ pattern' = tokens }) input'
|
||||
go state@MatchState{ pattern' = AtLeastMatchToken chars : tokens } input'
|
||||
| Just (nextCharacter, leftOver) <- Text.uncons input'
|
||||
, nextCharacter `elem` chars =
|
||||
go (matchSymbolToken state{ pattern' = OneOfMatchToken chars : tokens } nextCharacter) leftOver
|
||||
| otherwise = Nothing
|
||||
-- All tokens are processed, but there is still some input left.
|
||||
go MatchState{ pattern' = [] } _ = Nothing
|
||||
matchSymbolToken state nextCharacter
|
||||
| getField @"ignoring" state = state
|
||||
| otherwise = state
|
||||
{ matched = Text.snoc (getField @"matched" state) nextCharacter
|
||||
}
|
||||
|
||||
parsePattern :: Text -> [MatchToken]
|
||||
parsePattern input'
|
||||
| Just (firstChar, remaining) <- Text.uncons input'
|
||||
, firstChar == '\\' =
|
||||
case Text.uncons remaining of
|
||||
Nothing -> []
|
||||
Just ('d', remaining') -> OneOfMatchToken digits
|
||||
: parsePattern remaining'
|
||||
Just ('D', remaining') -> AtLeastMatchToken digits
|
||||
: parsePattern remaining'
|
||||
Just ('.', remaining') -> AtLeastMatchToken ('.' : digits)
|
||||
: parsePattern remaining'
|
||||
Just ('\\', remaining') -> SymbolMatchToken '\\'
|
||||
: parsePattern remaining'
|
||||
Just (_, remaining') -> parsePattern remaining'
|
||||
| Just (firstChar, remaining) <- Text.uncons input'
|
||||
, firstChar == '['
|
||||
, Just lastBracket <- Text.findIndex (== ']') remaining
|
||||
= OneOfMatchToken (Text.unpack $ Text.take lastBracket remaining)
|
||||
: parsePattern (Text.drop (succ lastBracket) remaining)
|
||||
| Just (firstChar, remaining) <- Text.uncons input' =
|
||||
let token =
|
||||
case firstChar of
|
||||
'*' -> OneOfMatchToken (toEnum <$> [32 .. 127])
|
||||
'(' -> OpenParenMatchToken
|
||||
')' -> CloseParenMatchToken
|
||||
s -> SymbolMatchToken s
|
||||
in token : parsePattern remaining
|
||||
| otherwise = []
|
||||
where
|
||||
digits = toEnum <$> [fromEnum '0' .. fromEnum '9']
|
||||
|
||||
-- * Packagist
|
||||
|
||||
newtype PackagistPackage = PackagistPackage
|
||||
{ version :: Text
|
||||
} deriving (Eq, Show)
|
||||
|
||||
$(deriveJSON defaultOptions ''PackagistPackage)
|
||||
|
||||
newtype PackagistResponse = PackagistResponse
|
||||
{ packages :: HashMap Text (Vector PackagistPackage)
|
||||
} deriving (Eq, Show)
|
||||
|
||||
$(deriveJSON defaultOptions ''PackagistResponse)
|
||||
|
||||
latestPackagist :: PackageOwner -> SlackBuilderT (Maybe Text)
|
||||
latestPackagist PackageOwner{..} = do
|
||||
packagistResponse <- runReq defaultHttpConfig $
|
||||
let uri = https "repo.packagist.org" /: "p2"
|
||||
/: owner
|
||||
/: name <> ".json"
|
||||
in req GET uri NoReqBody jsonResponse mempty
|
||||
let packagistPackages = getField @"packages"
|
||||
$ Network.HTTP.Req.responseBody (packagistResponse :: JsonResponse PackagistResponse)
|
||||
fullName = Text.intercalate "/" [owner, name]
|
||||
|
||||
pure $ HashMap.lookup fullName packagistPackages
|
||||
>>= fmap (getField @"version" . fst) . Vector.uncons
|
||||
|
||||
-- * Remote text file
|
||||
|
||||
data TextArguments = TextArguments
|
||||
{ textURL :: Text
|
||||
, versionPicker :: [String]
|
||||
}
|
||||
|
||||
latestText :: TextArguments -> Text -> SlackBuilderT (Maybe Text)
|
||||
latestText TextArguments{..} pattern' = do
|
||||
uri' <- mkURI textURL
|
||||
versions <- case versionPicker of
|
||||
(command : arguments) ->
|
||||
runReq defaultHttpConfig $ reqGet uri' $ readResponse command arguments
|
||||
[] -> runReq defaultHttpConfig $ reqGet uri' go
|
||||
pure $ listToMaybe $ mapMaybe (match pattern') versions
|
||||
where
|
||||
readResponse :: String -> [String] -> Response BodyReader -> IO [Text]
|
||||
readResponse command arguments response = do
|
||||
let createProcess' = proc command arguments
|
||||
(_, stdout', _) <- sourceProcessWithStreams createProcess' (responseBodySource response) stdoutReader sinkNull
|
||||
pure stdout'
|
||||
stdoutReader = decodeUtf8C .| linesUnboundedC .| CL.consume
|
||||
go response = runConduit $ responseBodySource response .| stdoutReader
|
||||
|
||||
-- * GitHub
|
||||
|
||||
newtype GhRefNode = GhRefNode
|
||||
{ name :: Text
|
||||
} deriving (Eq, Show)
|
||||
|
||||
$(deriveJSON defaultOptions ''GhRefNode)
|
||||
|
||||
newtype GhRef = GhRef
|
||||
{ nodes :: Vector GhRefNode
|
||||
} deriving (Eq, Show)
|
||||
|
||||
$(deriveJSON defaultOptions ''GhRef)
|
||||
|
||||
newtype GhRepository = GhRepository
|
||||
{ refs :: GhRef
|
||||
} deriving (Eq, Show)
|
||||
|
||||
$(deriveJSON defaultOptions ''GhRepository)
|
||||
|
||||
newtype GhData = GhData
|
||||
{ repository :: GhRepository
|
||||
} deriving (Eq, Show)
|
||||
|
||||
instance Aeson.FromJSON GhData where
|
||||
parseJSON (Aeson.Object keyMap)
|
||||
| Just data' <- KeyMap.lookup "data" keyMap =
|
||||
GhData <$> Aeson.withObject "GhData" (.: "repository") data'
|
||||
parseJSON _ = fail "data key not found in the response"
|
||||
|
||||
data GhVariables = GhVariables
|
||||
{ name :: Text
|
||||
, owner :: Text
|
||||
, prefix :: Maybe Text
|
||||
} deriving (Eq, Show)
|
||||
|
||||
$(deriveJSON defaultOptions ''GhVariables)
|
||||
|
||||
data GhQuery = GhQuery
|
||||
{ query :: Text
|
||||
, variables :: GhVariables
|
||||
} deriving (Eq, Show)
|
||||
|
||||
$(deriveJSON defaultOptions ''GhQuery)
|
||||
|
||||
latestGitHub
|
||||
:: PackageOwner
|
||||
-> Text
|
||||
-> SlackBuilderT (Maybe Text)
|
||||
latestGitHub PackageOwner{..} pattern' = do
|
||||
ghToken' <- SlackBuilderT $ asks ghToken
|
||||
ghResponse <- runReq defaultHttpConfig $
|
||||
let uri = https "api.github.com" /: "graphql"
|
||||
prefix = Text.takeWhile isAlpha
|
||||
$ Text.filter (liftA2 (&&) (/= ')') (/= '(')) pattern'
|
||||
query = GhQuery
|
||||
{ query = githubQuery
|
||||
, variables = GhVariables
|
||||
{ owner = owner
|
||||
, name = name
|
||||
, prefix = if Text.null prefix then Nothing else Just $ prefix <> "*"
|
||||
}
|
||||
}
|
||||
authorizationHeader = header "authorization"
|
||||
$ Text.Encoding.encodeUtf8
|
||||
$ "Bearer " <> ghToken'
|
||||
in req POST uri (ReqBodyJson query) jsonResponse
|
||||
$ authorizationHeader <> header "User-Agent" "SlackBuilder"
|
||||
let ghNodes = nodes
|
||||
$ refs
|
||||
$ (getField @"repository" :: GhData -> GhRepository)
|
||||
$ Network.HTTP.Req.responseBody ghResponse
|
||||
refs' = Vector.catMaybes
|
||||
$ match pattern' . getField @"name" <$> ghNodes
|
||||
pure $ refs' !? 0
|
||||
where
|
||||
githubQuery =
|
||||
"query ($name: String!, $owner: String!, $prefix: String) {\n\
|
||||
\ repository(name: $name, owner: $owner) {\n\
|
||||
\ refs(first: 10, query: $prefix, refPrefix: \"refs/tags/\", orderBy: {\n\
|
||||
\ field: TAG_COMMIT_DATE, direction: DESC\n\
|
||||
\ }) {\n\
|
||||
\ nodes {\n\
|
||||
\ id,\n\
|
||||
\ name\n\
|
||||
\ }\n\
|
||||
\ }\n\
|
||||
\ }\n\
|
||||
\}"
|
81
lib/SlackBuilder/Package.hs
Normal file
81
lib/SlackBuilder/Package.hs
Normal file
@ -0,0 +1,81 @@
|
||||
{- This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||
v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
obtain one at https://mozilla.org/MPL/2.0/. -}
|
||||
|
||||
-- | Contains data describing packages, methods to update them and to request
|
||||
-- information about them.
|
||||
module SlackBuilder.Package
|
||||
( DataBaseEntry(..)
|
||||
, Download(..)
|
||||
, DownloadTemplate(..)
|
||||
, PackageDescription(..)
|
||||
, PackageUpdateData(..)
|
||||
, Updater(..)
|
||||
, renderDownloadWithVersion
|
||||
, renderTextWithVersion
|
||||
) where
|
||||
|
||||
import Data.Text (Text)
|
||||
import qualified Data.Text as Text
|
||||
import Text.URI (URI(..))
|
||||
import qualified Text.URI as URI
|
||||
import Crypto.Hash (Digest, MD5)
|
||||
import SlackBuilder.Trans
|
||||
import Control.Monad.Catch (MonadThrow)
|
||||
import Data.Map (Map)
|
||||
|
||||
-- | Contains information how a package can be updated.
|
||||
data PackageDescription = PackageDescription
|
||||
{ latest :: Updater
|
||||
, downloaders :: Map Text Updater
|
||||
, name :: Text
|
||||
}
|
||||
|
||||
data PackageUpdateData = PackageUpdateData
|
||||
{ description :: PackageDescription
|
||||
, category :: Text
|
||||
, version :: Text
|
||||
}
|
||||
|
||||
-- | Download URI with the MD5 checksum of the target.
|
||||
data Download = Download
|
||||
{ download :: URI
|
||||
, md5sum :: Digest MD5
|
||||
} deriving (Eq, Show)
|
||||
|
||||
-- | List of URI components, including version placeholders.
|
||||
newtype DownloadTemplate = DownloadTemplate
|
||||
{ unDownloadTemplate :: Text
|
||||
} deriving Eq
|
||||
|
||||
instance Show DownloadTemplate
|
||||
where
|
||||
show = Text.unpack . unDownloadTemplate
|
||||
|
||||
-- | Replaces placeholders in the URL template with the given version.
|
||||
renderDownloadWithVersion :: MonadThrow m => DownloadTemplate -> Text -> m URI
|
||||
renderDownloadWithVersion (DownloadTemplate template) version =
|
||||
URI.mkURI $ renderTextWithVersion template version
|
||||
|
||||
-- | Replaces placeholders in the text with the given version.
|
||||
renderTextWithVersion :: Text -> Text -> Text
|
||||
renderTextWithVersion template version = Text.replace "{version}" version template
|
||||
|
||||
-- | Function used to get the latest version of a source.
|
||||
data Updater = Updater
|
||||
{ detectLatest :: SlackBuilderT (Maybe Text)
|
||||
, is64 :: Bool
|
||||
, getVersion :: Text -> Text -> SlackBuilderT Download
|
||||
}
|
||||
|
||||
data DataBaseEntry = DataBaseEntry
|
||||
{ name :: Text
|
||||
, version :: Text
|
||||
, arch :: Text
|
||||
, build :: Text
|
||||
} deriving Eq
|
||||
|
||||
instance Show DataBaseEntry
|
||||
where
|
||||
show DataBaseEntry{..} = Text.unpack
|
||||
$ Text.intercalate "-" [name, version, arch, build]
|
98
lib/SlackBuilder/Trans.hs
Normal file
98
lib/SlackBuilder/Trans.hs
Normal file
@ -0,0 +1,98 @@
|
||||
{- This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||
v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
obtain one at https://mozilla.org/MPL/2.0/. -}
|
||||
|
||||
-- | Transformers and exceptions.
|
||||
module SlackBuilder.Trans
|
||||
( SlackBuilderException(..)
|
||||
, SlackBuilderT(..)
|
||||
, relativeToRepository
|
||||
) where
|
||||
|
||||
import Control.Monad.Trans.Reader (ReaderT(..), asks)
|
||||
import Data.ByteString (ByteString)
|
||||
import Data.Text (Text)
|
||||
import qualified Data.Text as Text
|
||||
import SlackBuilder.Config
|
||||
import Control.Monad.IO.Class (MonadIO(..))
|
||||
import Control.Monad.Catch (MonadCatch(..), MonadThrow(..))
|
||||
import Control.Exception (Exception(..))
|
||||
import System.FilePath ((</>))
|
||||
import Text.URI (URI)
|
||||
import qualified Text.URI as URI
|
||||
import qualified Codec.Compression.Lzma as Lzma
|
||||
import Text.Megaparsec (ParseErrorBundle(..), errorBundlePretty)
|
||||
import Conduit (Void)
|
||||
|
||||
data SlackBuilderException
|
||||
= UpdaterNotFound Text
|
||||
| UnsupportedUrlType URI
|
||||
| LzmaDecompressionFailed Lzma.LzmaRet
|
||||
| MalformedInfoFile (ParseErrorBundle ByteString Void)
|
||||
deriving Show
|
||||
|
||||
instance Exception SlackBuilderException
|
||||
where
|
||||
displayException (UpdaterNotFound updateName) = Text.unpack
|
||||
$ Text.concat ["Requested package \"", updateName, "\" was not found"]
|
||||
displayException (UnsupportedUrlType givenURI) = Text.unpack
|
||||
$ "Only https URLs are supported, got: " <> URI.render givenURI
|
||||
displayException (LzmaDecompressionFailed Lzma.LzmaRetOK) =
|
||||
"Operation completed successfully"
|
||||
displayException (LzmaDecompressionFailed Lzma.LzmaRetStreamEnd) =
|
||||
"End of stream was reached"
|
||||
displayException (LzmaDecompressionFailed Lzma.LzmaRetUnsupportedCheck) =
|
||||
"Cannot calculate the integrity check"
|
||||
displayException (LzmaDecompressionFailed Lzma.LzmaRetGetCheck) =
|
||||
"Integrity check type is now available"
|
||||
displayException (LzmaDecompressionFailed Lzma.LzmaRetMemError) =
|
||||
"Cannot allocate memory"
|
||||
displayException (LzmaDecompressionFailed Lzma.LzmaRetMemlimitError) =
|
||||
"Memory usage limit was reached"
|
||||
displayException (LzmaDecompressionFailed Lzma.LzmaRetFormatError) =
|
||||
"File format not recognized"
|
||||
displayException (LzmaDecompressionFailed Lzma.LzmaRetOptionsError) =
|
||||
"Invalid or unsupported options"
|
||||
displayException (LzmaDecompressionFailed Lzma.LzmaRetDataError) =
|
||||
"Data is corrupt"
|
||||
displayException (LzmaDecompressionFailed Lzma.LzmaRetBufError) =
|
||||
"No progress is possible"
|
||||
displayException (LzmaDecompressionFailed Lzma.LzmaRetProgError) =
|
||||
"Programming error"
|
||||
displayException (MalformedInfoFile errorBundle) =
|
||||
errorBundlePretty errorBundle
|
||||
|
||||
newtype SlackBuilderT a = SlackBuilderT
|
||||
{ runSlackBuilderT :: ReaderT Settings IO a
|
||||
}
|
||||
|
||||
relativeToRepository :: FilePath -> SlackBuilderT FilePath
|
||||
relativeToRepository filePath =
|
||||
(</> filePath) <$> SlackBuilderT (asks repository)
|
||||
|
||||
instance Functor SlackBuilderT
|
||||
where
|
||||
fmap f (SlackBuilderT slackBuilderT) = SlackBuilderT $ f <$> slackBuilderT
|
||||
|
||||
instance Applicative SlackBuilderT
|
||||
where
|
||||
pure = SlackBuilderT . pure
|
||||
(SlackBuilderT f) <*> (SlackBuilderT x) = SlackBuilderT $ f <*> x
|
||||
|
||||
instance Monad SlackBuilderT
|
||||
where
|
||||
return = pure
|
||||
(SlackBuilderT x) >>= f = SlackBuilderT $ x >>= runSlackBuilderT . f
|
||||
|
||||
instance MonadIO SlackBuilderT
|
||||
where
|
||||
liftIO = SlackBuilderT . liftIO
|
||||
|
||||
instance MonadThrow SlackBuilderT
|
||||
where
|
||||
throwM = SlackBuilderT . throwM
|
||||
|
||||
instance MonadCatch SlackBuilderT
|
||||
where
|
||||
catch (SlackBuilderT action) handler =
|
||||
SlackBuilderT $ catch action $ runSlackBuilderT . handler
|
170
lib/download.rb
170
lib/download.rb
@ -1,170 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../config/config'
|
||||
require_relative 'package'
|
||||
require 'net/http'
|
||||
require 'pathname'
|
||||
require 'progressbar'
|
||||
require 'term/ansicolor'
|
||||
|
||||
module SlackBuilder
|
||||
extend Rake::FileUtilsExt
|
||||
|
||||
def self.clone(repo, package, tag_prefix = 'v')
|
||||
repository = Pathname.new('pkg') + package.name_version
|
||||
|
||||
if repository.directory?
|
||||
sh 'git', '-C', repository.to_path, 'remote', 'update', '--prune'
|
||||
else
|
||||
sh 'git', 'clone', repo, repository.to_path
|
||||
end
|
||||
|
||||
sh 'git', '-C', repository.to_path, 'checkout', "#{tag_prefix}#{package.version}"
|
||||
sh 'git', '-C', repository.to_path, 'submodule', 'update', '--init', '--recursive'
|
||||
|
||||
repository
|
||||
end
|
||||
end
|
||||
|
||||
def write_chunk(response, checksum, progressbar, io)
|
||||
response.read_body do |chunk|
|
||||
progressbar.progress += chunk.length
|
||||
io << chunk
|
||||
checksum << chunk
|
||||
end
|
||||
end
|
||||
|
||||
def write_download(target, response)
|
||||
checksum = Digest::MD5.new
|
||||
progressbar = ProgressBar.create title: target, total: response.header.content_length
|
||||
|
||||
File.open target, 'w' do |io|
|
||||
write_chunk response, checksum, progressbar, io
|
||||
end
|
||||
progressbar.finish
|
||||
|
||||
checksum
|
||||
end
|
||||
|
||||
def redirect_download(location, target)
|
||||
puts 'redirecting...'
|
||||
new_location = URI location
|
||||
|
||||
download new_location, target
|
||||
end
|
||||
|
||||
def start_download(uri, target, http)
|
||||
request = Net::HTTP::Get.new uri
|
||||
|
||||
http.request request do |response|
|
||||
case response
|
||||
when Net::HTTPRedirection
|
||||
return redirect_download response['location'], target
|
||||
else
|
||||
return write_download target, response
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def download(uri, target)
|
||||
print Term::ANSIColor.green "Downloading #{uri} "
|
||||
checksum = nil
|
||||
|
||||
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
||||
checksum = start_download uri, target, http
|
||||
end
|
||||
|
||||
puts
|
||||
checksum
|
||||
end
|
||||
|
||||
def hosted_sources(absolute_url)
|
||||
CONFIG[:download_url] + absolute_url
|
||||
end
|
||||
|
||||
def remote_file_exists?(url)
|
||||
uri = URI hosted_sources(url)
|
||||
|
||||
request = Net::HTTP.new uri.host, uri.port
|
||||
request.use_ssl = true
|
||||
response = request.request_head uri.path
|
||||
|
||||
response.code.to_i == 200
|
||||
end
|
||||
|
||||
def upload_command(local_path, remote_path)
|
||||
['scp', "slackbuilds/#{local_path}", CONFIG[:remote_path] + remote_path]
|
||||
end
|
||||
|
||||
def clone_and_archive(repo, name_version, tarball, tag_prefix = 'v')
|
||||
_, _, version = name_version.rpartition '-'
|
||||
|
||||
rm_rf name_version
|
||||
|
||||
sh 'git', 'clone', repo, name_version
|
||||
sh 'git', '-C', name_version, 'checkout', "#{tag_prefix}#{version}"
|
||||
sh 'git', '-C', name_version, 'submodule', 'update', '--init', '--recursive'
|
||||
|
||||
sh 'tar', 'Jcvf', "slackbuilds/#{tarball}", name_version
|
||||
rm_rf name_version
|
||||
end
|
||||
|
||||
def clone(repo, tarball, tag_prefix = 'v')
|
||||
name_version = File.basename tarball, '.tar.xz'
|
||||
remote_path = tarball[tarball.index('/')..]
|
||||
|
||||
if remote_file_exists?(remote_path)
|
||||
uri = URI hosted_sources(remote_path)
|
||||
|
||||
return download(uri, "slackbuilds/#{tarball}").hexdigest
|
||||
end
|
||||
|
||||
clone_and_archive repo, name_version, tarball, tag_prefix
|
||||
|
||||
sh(*upload_command(tarball, remote_path))
|
||||
|
||||
Digest::MD5.hexdigest File.read("slackbuilds/#{tarball}")
|
||||
end
|
||||
|
||||
def download_and_deploy(uri, tarball)
|
||||
remote_path = tarball[tarball.index('/')..]
|
||||
|
||||
if remote_file_exists?(remote_path)
|
||||
uri = URI hosted_sources(remote_path)
|
||||
return download(uri, "slackbuilds/#{tarball}").hexdigest
|
||||
end
|
||||
|
||||
checksum = download uri, "slackbuilds/#{tarball}"
|
||||
sh(*upload_command(tarball, remote_path))
|
||||
checksum.hexdigest
|
||||
end
|
||||
|
||||
def write_info(package, downloads:)
|
||||
File.write "slackbuilds/#{package.path}/#{package.name}.info",
|
||||
info_template(package, downloads)
|
||||
end
|
||||
|
||||
def update_slackbuild_version(package_path, version)
|
||||
name = package_path.split('/').last
|
||||
slackbuild_filename = "slackbuilds/#{package_path}/#{name}.SlackBuild"
|
||||
slackbuild_contents = File.read(slackbuild_filename)
|
||||
.gsub(/^VERSION=\${VERSION:-.+/, "VERSION=${VERSION:-#{version}}")
|
||||
|
||||
File.open(slackbuild_filename, 'w') { |file| file.puts slackbuild_contents }
|
||||
end
|
||||
|
||||
def commit(package_path, version)
|
||||
message = "#{package_path}: Updated for version #{version}"
|
||||
|
||||
unless system('git', '-C', 'slackbuilds', 'checkout', CONFIG[:branch],
|
||||
err: '/dev/null')
|
||||
sh 'git', '-C', 'slackbuilds', 'checkout', '-b', CONFIG[:branch], 'master'
|
||||
end
|
||||
sh 'git', '-C', 'slackbuilds', 'add', package_path
|
||||
sh 'git', '-C', 'slackbuilds', 'commit', '-S', '-m', message
|
||||
# sh 'git', '-C', 'slackbuilds', 'push', 'origin', CONFIG[:branch]
|
||||
end
|
@ -1,76 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Package
|
||||
attr_reader :path, :version, :homepage, :requires
|
||||
|
||||
def initialize(path, version:, homepage:, requires: [])
|
||||
@path = path
|
||||
@version = version
|
||||
@homepage = homepage
|
||||
@requires = requires
|
||||
end
|
||||
|
||||
def name
|
||||
File.basename @path
|
||||
end
|
||||
|
||||
def name_version
|
||||
"#{name}-#{@version}"
|
||||
end
|
||||
end
|
||||
|
||||
class Download
|
||||
attr_reader :download, :md5sum
|
||||
|
||||
def initialize(download, md5sum, is64: false)
|
||||
@download = download
|
||||
@md5sum = md5sum
|
||||
@is64 = is64
|
||||
end
|
||||
|
||||
def is64?
|
||||
@is64
|
||||
end
|
||||
end
|
||||
|
||||
def info_template(package, downloads)
|
||||
downloads64, downloads32 = downloads.partition(&:is64?)
|
||||
download32, md5sum32, download64, md5sum64 = download_entries downloads64, downloads32
|
||||
|
||||
<<~INFO_FILE
|
||||
PRGNAM="#{package.name}"
|
||||
VERSION="#{package.version}"
|
||||
HOMEPAGE="#{package.homepage}"
|
||||
DOWNLOAD="#{download32}"
|
||||
MD5SUM="#{md5sum32}"
|
||||
DOWNLOAD_x86_64="#{download64}"
|
||||
MD5SUM_x86_64="#{md5sum64}"
|
||||
REQUIRES="#{requires_entry package.requires}"
|
||||
MAINTAINER="Eugene Wissner"
|
||||
EMAIL="belka@caraus.de"
|
||||
INFO_FILE
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def requires_entry(requires)
|
||||
requires * ' '
|
||||
end
|
||||
|
||||
def download_entries(downloads64, downloads32)
|
||||
download32 =
|
||||
if downloads32.empty? && !downloads64.empty?
|
||||
'UNSUPPORTED'
|
||||
else
|
||||
downloads32.map(&:download) * " \\\n "
|
||||
end
|
||||
md5sum32 = downloads32.map(&:md5sum) * " \\\n "
|
||||
download64 = downloads64.map(&:download) * " \\\n "
|
||||
md5sum64 = downloads64.map(&:md5sum) * " \\\n "
|
||||
|
||||
[download32, md5sum32, download64, md5sum64]
|
||||
end
|
@ -1,4 +0,0 @@
|
||||
Colm is a programming language designed for the analysis and
|
||||
and transformation of computer languages.
|
||||
Colm is influenced primarily by TXL.
|
||||
It is in the family of program transformation languages.
|
@ -1,112 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Slackware build script for colm
|
||||
|
||||
# Copyright 2017-2019 Matteo Bernardini <ponce@slackbuilds.org>, Pisa, Italy
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use of this script, with or without modification, is
|
||||
# permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of this script must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
cd $(dirname $0) ; CWD=$(pwd)
|
||||
|
||||
PRGNAM=colm
|
||||
VERSION=${VERSION:-0.14.7}
|
||||
BUILD=${BUILD:-1}
|
||||
TAG=${TAG:-_SBo}
|
||||
PKGTYPE=${PKGTYPE:-tgz}
|
||||
|
||||
if [ -z "$ARCH" ]; then
|
||||
case "$( uname -m )" in
|
||||
i?86) ARCH=i586 ;;
|
||||
arm*) ARCH=arm ;;
|
||||
*) ARCH=$( uname -m ) ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# If the variable PRINT_PACKAGE_NAME is set, then this script will report what
|
||||
# the name of the created package would be, and then exit. This information
|
||||
# could be useful to other scripts.
|
||||
if [ ! -z "${PRINT_PACKAGE_NAME}" ]; then
|
||||
echo "$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TMP=${TMP:-/tmp/SBo}
|
||||
PKG=$TMP/package-$PRGNAM
|
||||
OUTPUT=${OUTPUT:-/tmp}
|
||||
|
||||
if [ "$ARCH" = "i586" ]; then
|
||||
SLKCFLAGS="-O2 -march=i586 -mtune=i686"
|
||||
LIBDIRSUFFIX=""
|
||||
elif [ "$ARCH" = "i686" ]; then
|
||||
SLKCFLAGS="-O2 -march=i686 -mtune=i686"
|
||||
LIBDIRSUFFIX=""
|
||||
elif [ "$ARCH" = "x86_64" ]; then
|
||||
SLKCFLAGS="-O2 -fPIC"
|
||||
LIBDIRSUFFIX="64"
|
||||
else
|
||||
SLKCFLAGS="-O2"
|
||||
LIBDIRSUFFIX=""
|
||||
fi
|
||||
|
||||
DOCS="COPYING README"
|
||||
|
||||
set -e
|
||||
|
||||
rm -rf $PKG
|
||||
mkdir -p $TMP $PKG $OUTPUT
|
||||
cd $TMP
|
||||
|
||||
rm -rf $PRGNAM-$VERSION
|
||||
tar xvf $CWD/$PRGNAM-$VERSION.tar.?z*
|
||||
cd $PRGNAM-$VERSION
|
||||
chown -R root:root .
|
||||
find -L . \
|
||||
\( -perm 777 -o -perm 775 -o -perm 750 -o -perm 711 -o -perm 555 \
|
||||
-o -perm 511 \) -exec chmod 755 {} \; -o \
|
||||
\( -perm 666 -o -perm 664 -o -perm 640 -o -perm 600 -o -perm 444 \
|
||||
-o -perm 440 -o -perm 400 \) -exec chmod 644 {} \;
|
||||
|
||||
autoreconf -fi
|
||||
|
||||
CFLAGS="$SLKCFLAGS" \
|
||||
CXXFLAGS="$SLKCFLAGS" \
|
||||
./configure \
|
||||
--prefix=/usr \
|
||||
--libdir=/usr/lib${LIBDIRSUFFIX} \
|
||||
--sysconfdir=/etc \
|
||||
--localstatedir=/var \
|
||||
--mandir=/usr/man \
|
||||
--docdir=/usr/doc/$PRGNAM-$VERSION \
|
||||
--build=$ARCH-slackware-linux
|
||||
|
||||
make
|
||||
make install DESTDIR=$PKG
|
||||
|
||||
find $PKG -print0 | xargs -0 file | grep -e "executable" -e "shared object" | grep ELF \
|
||||
| cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null || true
|
||||
|
||||
mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION
|
||||
cp -a $DOCS $PKG/usr/doc/$PRGNAM-$VERSION
|
||||
cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild
|
||||
|
||||
mkdir -p $PKG/install
|
||||
cat $CWD/slack-desc > $PKG/install/slack-desc
|
||||
|
||||
cd $PKG
|
||||
/sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE
|
@ -1,10 +0,0 @@
|
||||
PRGNAM="colm"
|
||||
VERSION="0.14.7"
|
||||
HOMEPAGE="https://www.colm.net/open-source/colm/"
|
||||
DOWNLOAD="https://www.colm.net/files/colm/colm-0.14.7.tar.gz"
|
||||
MD5SUM="073b11234fe64a281874b4466c0c25ee"
|
||||
DOWNLOAD_x86_64=""
|
||||
MD5SUM_x86_64=""
|
||||
REQUIRES=""
|
||||
MAINTAINER="Matteo Bernardini"
|
||||
EMAIL="ponce@slackbuilds.org"
|
@ -1,19 +0,0 @@
|
||||
# HOW TO EDIT THIS FILE:
|
||||
# The "handy ruler" below makes it easier to edit a package description.
|
||||
# Line up the first '|' above the ':' following the base package name, and
|
||||
# the '|' on the right side marks the last column you can put a character in.
|
||||
# You must make exactly 11 lines for the formatting to be correct. It's also
|
||||
# customary to leave one space after the ':' except on otherwise blank lines.
|
||||
|
||||
|-----handy-ruler------------------------------------------------------|
|
||||
colm: colm (Programming language)
|
||||
colm:
|
||||
colm: Colm is a programming language designed for the analysis and
|
||||
colm: and transformation of computer languages.
|
||||
colm: Colm is influenced primarily by TXL.
|
||||
colm: It is in the family of program transformation languages.
|
||||
colm:
|
||||
colm: homepage: https://www.colm.net/open-source/colm/
|
||||
colm:
|
||||
colm:
|
||||
colm:
|
@ -1,182 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright 2008, 2009, 2010, 2012, 2013, 2014, 2017, 2018, 2020, 2021 Patrick J. Volkerding, Sebeka, Minnesota, USA
|
||||
# Copyright 2011, 2012, 2013, 2014, 2017 Heinz Wiesinger, Amsterdam, The Netherlands
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use of this script, with or without modification, is
|
||||
# permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of this script must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# Build and install MySQL on Slackware
|
||||
# by: David Cantrell <david@slackware.com>
|
||||
# MariaDB conversion by: Heinz Wiesinger <pprkut@liwjatan.at>
|
||||
# Also maintained by: Patrick Volkerding <volkerdi@slackware.com>
|
||||
|
||||
cd $(dirname $0) ; CWD=$(pwd)
|
||||
|
||||
PKGNAM=mysql
|
||||
VERSION=${VERSION:-8.0.30}
|
||||
BUILD=${BUILD:-1}
|
||||
|
||||
# To reduce the package size, the embedded server may be omitted. Currently
|
||||
# only amarok uses this. To build without embedded support, set this to NO.
|
||||
EMBEDDED=${EMBEDDED:-YES}
|
||||
|
||||
# Add a description tag to the $BUILD. This is used by
|
||||
# "build_embedded_package.sh" to mark packages containing the embedded server,
|
||||
# but can optionally be used with any kind of custom tag desired.
|
||||
TAG=${TAG:-}
|
||||
|
||||
# Automatically determine the architecture we're building on:
|
||||
if [ -z "$ARCH" ]; then
|
||||
case "$( uname -m )" in
|
||||
i?86) export ARCH=i586 ;;
|
||||
arm*) export ARCH=arm ;;
|
||||
# Unless $ARCH is already set, use uname -m for all other archs:
|
||||
*) export ARCH=$( uname -m ) ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# If the variable PRINT_PACKAGE_NAME is set, then this script will report what
|
||||
# the name of the created package would be, and then exit. This information
|
||||
# could be useful to other scripts.
|
||||
if [ ! -z "${PRINT_PACKAGE_NAME}" ]; then
|
||||
echo "$PKGNAM-$VERSION-$ARCH-${BUILD}${TAG}.txz"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
NUMJOBS=${NUMJOBS:-" -j$(expr $(nproc) + 1) "}
|
||||
TMP=${TMP:-/tmp}
|
||||
PKG=$TMP/package-${PKGNAM}
|
||||
|
||||
if [ "$ARCH" = "i486" ]; then
|
||||
SLKCFLAGS="-O2 -march=i486 -mtune=i686"
|
||||
LIBDIRSUFFIX=""
|
||||
elif [ "$ARCH" = "i586" ]; then
|
||||
SLKCFLAGS="-O2 -march=i586 -mtune=i686"
|
||||
LIBDIRSUFFIX=""
|
||||
elif [ "$ARCH" = "i686" ]; then
|
||||
SLKCFLAGS="-O2 -march=i686 -mtune=i686"
|
||||
LIBDIRSUFFIX=""
|
||||
elif [ "$ARCH" = "x86_64" ]; then
|
||||
SLKCFLAGS="-O2 -fPIC"
|
||||
LIBDIRSUFFIX="64"
|
||||
fi
|
||||
|
||||
rm -rf $PKG
|
||||
mkdir -p $TMP $PKG
|
||||
cd $TMP
|
||||
rm -rf ${PKGNAM}-$VERSION
|
||||
tar xvf $CWD/${PKGNAM}-boost-$VERSION.tar.?z || exit 1
|
||||
cd ${PKGNAM}-$VERSION || exit 1
|
||||
|
||||
chown -R root:root .
|
||||
find . \
|
||||
\( -perm 777 -o -perm 775 -o -perm 711 -o -perm 555 -o -perm 511 \) \
|
||||
-exec chmod 755 {} \+ -o \
|
||||
\( -perm 666 -o -perm 664 -o -perm 600 -o -perm 444 -o -perm 440 -o -perm 400 \) \
|
||||
-exec chmod 644 {} \+
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake \
|
||||
-DCMAKE_C_FLAGS="$SLKCFLAGS" \
|
||||
-DCMAKE_CXX_FLAGS="$SLKCFLAGS" \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DFEATURE_SET="community" \
|
||||
-DINSTALL_LAYOUT="RPM" \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DINSTALL_LIBDIR="lib${LIBDIRSUFFIX}" \
|
||||
-DINSTALL_SBINDIR=libexec \
|
||||
-DINSTALL_INCLUDEDIR=include/mysql \
|
||||
-DINSTALL_MYSQLSHAREDIR=/usr/share/mysql \
|
||||
-DINSTALL_SQLBENCHDIR= \
|
||||
-DINSTALL_MYSQLTESTDIR=mysql-test \
|
||||
-DINSTALL_MANDIR=man \
|
||||
-DINSTALL_PLUGINDIR="/usr/lib${LIBDIRSUFFIX}/mysql/plugin" \
|
||||
-DINSTALL_SCRIPTDIR=bin \
|
||||
-DINSTALL_SUPPORTFILESDIR=/usr/share/mysql \
|
||||
-DINSTALL_MYSQLDATADIR="/var/lib/mysql" \
|
||||
-DINSTALL_DOCREADMEDIR="doc/${PKGNAM}-$VERSION" \
|
||||
-DINSTALL_DOCDIR="doc/${PKGNAM}-$VERSION" \
|
||||
-DMYSQL_DATADIR="/var/lib/mysql" \
|
||||
-DMYSQL_UNIX_ADDR="/var/run/mysql/mysql.sock" \
|
||||
-DWITH_EXTRA_CHARSETS=complex \
|
||||
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
|
||||
-DENABLED_LOCAL_INFILE=ON \
|
||||
-DWITH_EMBEDDED_SERVER=${EMBEDDED} \
|
||||
-DWITH_LIBARCHIVE=ON \
|
||||
-DWITH_READLINE=ON \
|
||||
-DWITH_ROCKSDB_JEMALLOC=ON \
|
||||
-DWITH_ZLIB=system \
|
||||
-DWITH_EXTERNAL_ZLIB=ON \
|
||||
-DWITH_SSL=system \
|
||||
-DWITH_BOOST="../boost" \
|
||||
-DCONC_WITH_SSL=ON \
|
||||
-DUSE_ARIA_FOR_TMP_TABLES=ON \
|
||||
-DAWS_SDK_EXTERNAL_PROJECT=OFF \
|
||||
.. || exit 1
|
||||
|
||||
# ruby mysql2 fails to run
|
||||
# -DWITH_JEMALLOC=system \
|
||||
|
||||
make $NUMJOBS || make || exit 1
|
||||
make install DESTDIR=$PKG || exit 1
|
||||
|
||||
# Sorry, I'm not going to put up with "/etc/systemd/" just for a config file
|
||||
# that isn't really needed anyway:
|
||||
rm -rf $PKG/etc/systemd
|
||||
|
||||
# Leave build directory:
|
||||
cd ..
|
||||
|
||||
# Remove large static libraries:
|
||||
rm -f $PKG/usr/lib${LIBDIRSUFFIX}/libmysqlclient.a
|
||||
|
||||
# Do not include the test suite:
|
||||
rm -rf $PKG/usr/mysql-test
|
||||
|
||||
# The ./configure option to omit this has gone away, so we'll omit it
|
||||
# the old-fashioned way. It's all in the source tarball if you need it.
|
||||
rm -rf $PKG/usr/sql-bench
|
||||
|
||||
# This is the directory where databases are stored
|
||||
mkdir -p $PKG/var/lib/mysql $PKG/var/lib/mysql-files
|
||||
chown mysql.mysql $PKG/var/lib/mysql $PKG/var/lib/mysql-files
|
||||
chmod 0750 $PKG/var/lib/mysql $PKG/var/lib/mysql-files
|
||||
|
||||
# This is where the socket is stored
|
||||
mkdir -p $PKG/var/run/mysql
|
||||
chown mysql.mysql $PKG/var/run/mysql
|
||||
chmod 0755 $PKG/var/run/mysql
|
||||
|
||||
rm -rf $PKG/etc/init.d $PKG/usr/libexec/rcmysql
|
||||
|
||||
# Mark config files under /etc as .new
|
||||
rm -rf $PKG/etc/logrotate.d
|
||||
|
||||
find $PKG | xargs file | grep -e "executable" -e "shared object" | grep ELF \
|
||||
| cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null
|
||||
|
||||
find $PKG/usr/man -type f -exec gzip -9 {} \+
|
||||
for i in $( find $PKG/usr/man -type l ) ; do ln -s $( readlink $i ).gz $i.gz ; rm $i ; done
|
||||
|
||||
mkdir -p $PKG/install
|
||||
cat $CWD/slack-desc > $PKG/install/slack-desc
|
||||
|
||||
cd $PKG
|
||||
/sbin/makepkg -l y -c n $TMP/${PKGNAM}-$VERSION-$ARCH-${BUILD}${TAG}.txz
|
@ -1,10 +0,0 @@
|
||||
PRGNAM="mysql"
|
||||
VERSION="8.0.30"
|
||||
HOMEPAGE="https://dev.mysql.com"
|
||||
DOWNLOAD=""
|
||||
MD5SUM=""
|
||||
DOWNLOAD_x86_64="https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-boost-8.0.30.tar.gz"
|
||||
MD5SUM_x86_64="313d625fcaa932bd87b48f0cf9b40f1c"
|
||||
REQUIRES=""
|
||||
MAINTAINER="Eugene Wissner"
|
||||
EMAIL="belka@caraus.de"
|
@ -1,19 +0,0 @@
|
||||
# HOW TO EDIT THIS FILE:
|
||||
# The "handy ruler" below makes it easier to edit a package description. Line
|
||||
# up the first '|' above the ':' following the base package name, and the '|'
|
||||
# on the right side marks the last column you can put a character in. You must
|
||||
# make exactly 11 lines for the formatting to be correct. It's also
|
||||
# customary to leave one space after the ':'.
|
||||
|
||||
|-----handy-ruler------------------------------------------------------|
|
||||
mysql: mysql (The MySQL Database Server)
|
||||
mysql:
|
||||
mysql: MySQL Server, the world's most popular open source database, and
|
||||
mysql: MySQL Cluster, a real-time, open source transactional database.
|
||||
mysql:
|
||||
mysql: Homepage: www.mysql.com/
|
||||
mysql:
|
||||
mysql:
|
||||
mysql:
|
||||
mysql:
|
||||
mysql:
|
@ -1,4 +0,0 @@
|
||||
PackageKit is a DBUS abstraction layer that allows the session user to manage
|
||||
packages in a secure way using a cross-distro, cross-architecture API.
|
||||
|
||||
The script requires bash-completion from extra.
|
@ -1,11 +0,0 @@
|
||||
--- a/meson.build 2022-12-01 19:47:48.000000000 +0100
|
||||
+++ b/meson.build 2022-12-05 13:10:39.303777801 +0100
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
elogind = []
|
||||
if get_option('elogind')
|
||||
- elogind = dependency('elogind', version: '>=229.4')
|
||||
+ elogind = dependency('libelogind', version: '>=229.4')
|
||||
add_project_arguments ('-DHAVE_SYSTEMD_SD_LOGIN_H=1', language: 'c')
|
||||
endif
|
||||
|
@ -1,120 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Slackware build script for packagekit
|
||||
#
|
||||
# Copyright 2022 Eugene Wissner, Germany, Dachau
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use of this script, with or without modification, is
|
||||
# permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of this script must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
cd $(dirname $0) ; CWD=$(pwd)
|
||||
|
||||
PRGNAM=packagekit
|
||||
VERSION=${VERSION:-1.2.6}
|
||||
BUILD=${BUILD:-1}
|
||||
TAG=${TAG:-_SBo}
|
||||
PKGTYPE=${PKGTYPE:-tgz}
|
||||
|
||||
SRCNAM=PackageKit
|
||||
|
||||
if [ -z "$ARCH" ]; then
|
||||
case "$( uname -m )" in
|
||||
i?86) ARCH=i586 ;;
|
||||
arm*) ARCH=arm ;;
|
||||
*) ARCH=$( uname -m ) ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# If the variable PRINT_PACKAGE_NAME is set, then this script will report what
|
||||
# the name of the created package would be, and then exit. This information
|
||||
# could be useful to other scripts.
|
||||
if [ ! -z "${PRINT_PACKAGE_NAME}" ]; then
|
||||
echo "$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TMP=${TMP:-/tmp}
|
||||
PKG=$TMP/package-$PRGNAM
|
||||
OUTPUT=${OUTPUT:-/tmp}
|
||||
|
||||
if [ "$ARCH" = "i586" ]; then
|
||||
SLKCFLAGS="-O2 -march=i586 -mtune=i686"
|
||||
LIBDIRSUFFIX=""
|
||||
elif [ "$ARCH" = "i686" ]; then
|
||||
SLKCFLAGS="-O2 -march=i686 -mtune=i686"
|
||||
LIBDIRSUFFIX=""
|
||||
elif [ "$ARCH" = "x86_64" ]; then
|
||||
SLKCFLAGS="-O2 -fPIC"
|
||||
LIBDIRSUFFIX="64"
|
||||
else
|
||||
SLKCFLAGS="-O2"
|
||||
LIBDIRSUFFIX=""
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
rm -rf $PKG
|
||||
mkdir -p $TMP $PKG $OUTPUT
|
||||
cd $TMP
|
||||
rm -rf $SRCNAM-$VERSION
|
||||
tar xvf $CWD/$SRCNAM-$VERSION.tar.xz
|
||||
cd $SRCNAM-$VERSION
|
||||
chown -R root:root .
|
||||
find -L . \
|
||||
\( -perm 777 -o -perm 775 -o -perm 750 -o -perm 711 -o -perm 555 \
|
||||
-o -perm 511 \) -exec chmod 755 {} \; -o \
|
||||
\( -perm 666 -o -perm 664 -o -perm 640 -o -perm 600 -o -perm 444 \
|
||||
-o -perm 440 -o -perm 400 \) -exec chmod 644 {} \;
|
||||
|
||||
patch -p1 --verbose -i $CWD/meson_elogind.patch
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
CFLAGS="$SLKCFLAGS" \
|
||||
CXXFLAGS="$SLKCFLAGS" \
|
||||
meson .. \
|
||||
--buildtype=release \
|
||||
--infodir=/usr/info \
|
||||
--libdir=/usr/lib${LIBDIRSUFFIX} \
|
||||
--localstatedir=/var \
|
||||
--prefix=/usr \
|
||||
--sysconfdir=/etc \
|
||||
-Dstrip=true \
|
||||
-Dsystemd=false \
|
||||
-Doffline_update=false \
|
||||
-Delogind=true \
|
||||
-Dpackaging_backend=slack
|
||||
"${NINJA:=ninja}"
|
||||
DESTDIR=$PKG $NINJA install
|
||||
cd ..
|
||||
|
||||
mv $PKG/usr/share/man $PKG/usr/man
|
||||
find $PKG/usr/man -type f -exec gzip -9 {} \;
|
||||
for i in $( find $PKG/usr/man -type l ) ; do ln -s $( readlink $i ).gz $i.gz ; rm $i ; done
|
||||
|
||||
mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION
|
||||
cp -a \
|
||||
AUTHORS COPYING HACKING MAINTAINERS NEWS README RELEASE \
|
||||
$PKG/usr/doc/$PRGNAM-$VERSION
|
||||
cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild
|
||||
|
||||
mkdir -p $PKG/install
|
||||
cat $CWD/slack-desc > $PKG/install/slack-desc
|
||||
|
||||
cd $PKG
|
||||
/sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE
|
@ -1,11 +0,0 @@
|
||||
PRGNAM="packagekit"
|
||||
VERSION="1.2.6"
|
||||
HOMEPAGE="https://www.freedesktop.org/software/PackageKit/"
|
||||
DOWNLOAD="https://www.freedesktop.org/software/PackageKit/releases/PackageKit-1.2.6.tar.xz"
|
||||
MD5SUM="71f855b4ac809b642ec911ce12dd8010"
|
||||
DOWNLOAD_x86_64=""
|
||||
MD5SUM_x86_64=""
|
||||
REQUIRES=""
|
||||
MAINTAINER="Eugene Wissner"
|
||||
EMAIL="belka@caraus.de"
|
||||
PackageKit-1.2.6.tar.xz
|
@ -1,19 +0,0 @@
|
||||
# HOW TO EDIT THIS FILE:
|
||||
# The "handy ruler" below makes it easier to edit a package description. Line
|
||||
# up the first '|' above the ':' following the base package name, and the '|'
|
||||
# on the right side marks the last column you can put a character in. You must
|
||||
# make exactly 11 lines for the formatting to be correct. It's also
|
||||
# customary to leave one space after the ':'.
|
||||
|
||||
|-----handy-ruler------------------------------------------------------|
|
||||
packagekit: PackageKit (A DBUS packaging abstraction layer)
|
||||
packagekit:
|
||||
packagekit: PackageKit is a DBUS abstraction layer that allows the session user to
|
||||
packagekit: packages in a secure way using a cross-distro, cross-architecture API.
|
||||
packagekit:
|
||||
packagekit: Homepage: https://www.freedesktop.org/software/PackageKit/
|
||||
packagekit:
|
||||
packagekit:
|
||||
packagekit:
|
||||
packagekit:
|
||||
packagekit:
|
@ -1,7 +0,0 @@
|
||||
PHP is an HTML-embedded scripting language. It shares syntax
|
||||
characteristics with C, Java, and Perl. The primary objective behind
|
||||
this language is to make a fast and easy-to-use scripting language for
|
||||
dynamic web sites.
|
||||
|
||||
This installation is compatible with the official php package and
|
||||
doesn't overwrit any stock files.
|
@ -1,18 +0,0 @@
|
||||
config() {
|
||||
NEW="$1"
|
||||
OLD="`dirname $NEW`/`basename $NEW .new`"
|
||||
# If there's no config file by that name, mv it over:
|
||||
if [ ! -r $OLD ]; then
|
||||
mv $NEW $OLD
|
||||
elif [ "`cat $OLD | md5sum`" = "`cat $NEW | md5sum`" ]; then # toss the redundant copy
|
||||
rm $NEW
|
||||
fi
|
||||
# Otherwise, we leave the .new copy for the admin to consider...
|
||||
}
|
||||
# Keep same perms on rc.php-fpm.new:
|
||||
if [ -e etc/rc.d/rc.php-fpm-8.1 ]; then
|
||||
cp -a etc/rc.d/rc.php-fpm-8.1 etc/rc.d/rc.php-fpm-8.1.new.incoming
|
||||
cat etc/rc.d/rc.php-fpm-8.1.new > etc/rc.d/rc.php-fpm-8.1.new.incoming
|
||||
mv etc/rc.d/rc.php-fpm-8.1.new.incoming etc/rc.d/rc.php-fpm-8.1.new
|
||||
fi
|
||||
config etc/rc.d/rc.php-fpm-8.1.new
|
@ -1,221 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Build and package PHP FPM 8.1
|
||||
# Copyright 2022 Eugene Wissner, Germany, Dachau
|
||||
#
|
||||
# by: David Cantrell <david@slackware.com>
|
||||
# Modified for PHP 4-5 by volkerdi@slackware.com
|
||||
# Copyright 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2015, 2017, 2019, 2020, 2021 Patrick Volkerding, Sebeka, MN, USA
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use of this script, with or without modification, is
|
||||
# permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of this script must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
cd $(dirname $0) ; CWD=$(pwd)
|
||||
|
||||
PRGNAM=php81
|
||||
VERSION=${VERSION:-8.1.13}
|
||||
BUILD=${BUILD:-1}
|
||||
TAG=${TAG:-_SBo}
|
||||
PKGTYPE=${PKGTYPE:-tgz}
|
||||
|
||||
VERSION_SUFFIX=8.1
|
||||
|
||||
if [ -z "$ARCH" ]; then
|
||||
case "$( uname -m )" in
|
||||
i?86) ARCH=i586 ;;
|
||||
arm*) ARCH=arm ;;
|
||||
*) ARCH=$( uname -m ) ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# If the variable PRINT_PACKAGE_NAME is set, then this script will report what
|
||||
# the name of the created package would be, and then exit. This information
|
||||
# could be useful to other scripts.
|
||||
if [ ! -z "${PRINT_PACKAGE_NAME}" ]; then
|
||||
echo "$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TMP=${TMP:-/tmp}
|
||||
PKG=$TMP/package-$PRGNAM
|
||||
OUTPUT=${OUTPUT:-/tmp}
|
||||
|
||||
if [ "$ARCH" = "i586" ]; then
|
||||
SLKCFLAGS="-O2 -march=i586 -mtune=i686"
|
||||
LIBDIRSUFFIX=""
|
||||
elif [ "$ARCH" = "i686" ]; then
|
||||
SLKCFLAGS="-O2 -march=i686 -mtune=i686"
|
||||
LIBDIRSUFFIX=""
|
||||
elif [ "$ARCH" = "x86_64" ]; then
|
||||
SLKCFLAGS="-O2 -fPIC"
|
||||
LIBDIRSUFFIX="64"
|
||||
else
|
||||
SLKCFLAGS="-O2"
|
||||
LIBDIRSUFFIX=""
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
rm -rf $PKG
|
||||
mkdir -p $TMP $PKG $OUTPUT
|
||||
cd $TMP
|
||||
rm -rf php-$VERSION
|
||||
tar xvf $CWD/php-$VERSION.tar.xz
|
||||
cd php-$VERSION
|
||||
chown -R root:root .
|
||||
|
||||
# Sometimes they ship a few of these:
|
||||
find . -name "*.orig" -delete
|
||||
|
||||
find -L . \
|
||||
\( -perm 777 -o -perm 775 -o -perm 750 -o -perm 711 -o -perm 555 \
|
||||
-o -perm 511 \) -exec chmod 755 {} \; -o \
|
||||
\( -perm 666 -o -perm 664 -o -perm 640 -o -perm 600 -o -perm 444 \
|
||||
-o -perm 440 -o -perm 400 \) -exec chmod 644 {} \;
|
||||
|
||||
sed -i "s|build$|php/${VERSION_SUFFIX}/build|" scripts/Makefile.frag
|
||||
sed -i "s|build\"$|php/${VERSION_SUFFIX}/build\"|" scripts/phpize.in
|
||||
|
||||
EXTENSION_DIR=/usr/lib${LIBDIRSUFFIX}/php/${VERSION_SUFFIX}/extensions \
|
||||
CFLAGS="$SLKCFLAGS -DU_DEFINE_FALSE_AND_TRUE=1" \
|
||||
CXXFLAGS="$SLKCFLAGS -DU_USING_ICU_NAMESPACE=1 -DU_DEFINE_FALSE_AND_TRUE=1" \
|
||||
./configure \
|
||||
--prefix=/usr \
|
||||
--libdir=/usr/lib${LIBDIRSUFFIX} \
|
||||
--with-libdir=lib${LIBDIRSUFFIX} \
|
||||
--localstatedir=/var \
|
||||
--sysconfdir=/etc/php/${VERSION_SUFFIX} \
|
||||
--datarootdir=/usr/share \
|
||||
--datadir=/usr/share \
|
||||
--infodir=/usr/info \
|
||||
--mandir=/usr/man \
|
||||
--program-suffix=-$VERSION_SUFFIX \
|
||||
--without-apxs2 \
|
||||
--enable-fpm \
|
||||
--with-fpm-user=apache \
|
||||
--with-fpm-group=apache \
|
||||
--enable-zts \
|
||||
--enable-pcntl \
|
||||
--enable-mbregex \
|
||||
--enable-tokenizer=shared \
|
||||
--with-config-file-scan-dir=/etc/php/${VERSION_SUFFIX}/php.d \
|
||||
--with-config-file-path=/etc/php/${VERSION_SUFFIX} \
|
||||
--with-layout=PHP \
|
||||
--disable-sigchild \
|
||||
--with-libxml \
|
||||
--with-expat \
|
||||
--enable-simplexml \
|
||||
--enable-xmlreader=shared \
|
||||
--enable-dom=shared \
|
||||
--enable-filter \
|
||||
--disable-debug \
|
||||
--with-openssl=shared \
|
||||
--with-external-pcre \
|
||||
--with-zlib=shared,/usr \
|
||||
--enable-bcmath=shared \
|
||||
--with-bz2=shared,/usr \
|
||||
--enable-calendar=shared \
|
||||
--enable-ctype=shared \
|
||||
--with-curl=shared \
|
||||
--enable-dba=shared \
|
||||
--with-gdbm=/usr \
|
||||
--with-db4=/usr \
|
||||
--enable-exif=shared \
|
||||
--enable-ftp=shared \
|
||||
--enable-gd=shared \
|
||||
--with-external-gd \
|
||||
--with-jpeg \
|
||||
--with-xpm \
|
||||
--with-gettext=shared,/usr \
|
||||
--with-gmp=shared,/usr \
|
||||
--with-iconv=shared \
|
||||
--with-imap-ssl=/usr \
|
||||
--with-pdo-pgsql=shared,/usr/bin/pg_config \
|
||||
--with-pgsql=shared,/usr/bin/pg_config \
|
||||
--with-ldap=shared \
|
||||
--enable-mbstring=shared \
|
||||
--enable-mysqlnd=shared \
|
||||
--with-mysqli=shared,mysqlnd \
|
||||
--with-mysql-sock=/var/run/mysql/mysql.sock \
|
||||
--with-iodbc=shared,/usr \
|
||||
--enable-pdo=shared \
|
||||
--with-pdo-mysql=shared,mysqlnd \
|
||||
--with-pdo-sqlite=shared,/usr \
|
||||
--with-pdo-odbc=shared,iODBC,/usr \
|
||||
--with-pspell=shared,/usr \
|
||||
--with-enchant=shared,/usr \
|
||||
--enable-shmop=shared \
|
||||
--with-snmp=shared,/usr \
|
||||
--enable-soap=shared \
|
||||
--enable-sockets \
|
||||
--with-sqlite3=shared \
|
||||
--enable-sysvmsg \
|
||||
--enable-sysvsem \
|
||||
--enable-sysvshm \
|
||||
--with-xsl=shared,/usr \
|
||||
--with-zip=shared \
|
||||
--enable-intl=shared \
|
||||
--enable-opcache \
|
||||
--enable-shared=yes \
|
||||
--enable-static=no \
|
||||
--with-gnu-ld \
|
||||
--with-pic \
|
||||
--enable-phpdbg \
|
||||
--with-sodium \
|
||||
--with-password-argon2 \
|
||||
--without-readline \
|
||||
--with-libedit \
|
||||
--with-pear=/usr/lib${LIBDIRSUFFIX}/php/${VERSION_SUFFIX} \
|
||||
--includedir=/usr/include/php/${VERSION_SUFFIX} \
|
||||
--with-tidy=shared \
|
||||
--build=$ARCH-slackware-linux
|
||||
|
||||
make
|
||||
make install INSTALL_ROOT=$PKG
|
||||
|
||||
mkdir -p $PKG/etc/rc.d
|
||||
cp sapi/fpm/init.d.php-fpm $PKG/etc/rc.d/rc.php-fpm-${VERSION_SUFFIX}.new
|
||||
chmod 644 $PKG/etc/rc.d/rc.php-fpm-${VERSION_SUFFIX}.new
|
||||
|
||||
# Strip ELF objects.
|
||||
find $PKG | xargs file | grep -e "executable" -e "shared object" | grep ELF \
|
||||
| cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null
|
||||
|
||||
find $PKG/usr/man -type f -exec gzip -9 {} \;
|
||||
for i in $( find $PKG/usr/man -type l ) ; do ln -s $( readlink $i ).gz $i.gz ; rm $i ; done
|
||||
|
||||
# PHP sometimes puts junk in the root directory:
|
||||
( cd $PKG
|
||||
rm -rf .channels .depdb .depdblock .filemap .lock .registry
|
||||
)
|
||||
|
||||
rm -r $PKG/usr/share/fpm $PKG/usr/bin/pear $PKG/usr/bin/peardev
|
||||
mv $PKG/usr/bin/pecl $PKG/usr/bin/pecl-${VERSION_SUFFIX}
|
||||
|
||||
mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION
|
||||
cp -a \
|
||||
CODING_STANDARDS* CONTRIBUTING* EXTENSIONS* LICENSE* NEWS* README* UPGRADING* \
|
||||
$PKG/usr/doc/$PRGNAM-$VERSION
|
||||
cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild
|
||||
|
||||
mkdir -p $PKG/install
|
||||
cat $CWD/slack-desc > $PKG/install/slack-desc
|
||||
cat $CWD/doinst.sh > $PKG/install/doinst.sh
|
||||
|
||||
cd $PKG
|
||||
/sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE
|
@ -1,10 +0,0 @@
|
||||
PRGNAM="php81"
|
||||
VERSION="8.1.13"
|
||||
HOMEPAGE="https://www.php.net/"
|
||||
DOWNLOAD="https://www.php.net/distributions/php-8.1.13.tar.xz"
|
||||
MD5SUM="43302de3d2c064f2f23c9693a2f17aeb"
|
||||
DOWNLOAD_x86_64=""
|
||||
MD5SUM_x86_64=""
|
||||
REQUIRES="postgresql"
|
||||
MAINTAINER="Eugene Wissner"
|
||||
EMAIL="belka@caraus.de"
|
@ -1,19 +0,0 @@
|
||||
# HOW TO EDIT THIS FILE:
|
||||
# The "handy ruler" below makes it easier to edit a package description. Line
|
||||
# up the first '|' above the ':' following the base package name, and the '|'
|
||||
# on the right side marks the last column you can put a character in. You must
|
||||
# make exactly 11 lines for the formatting to be correct. It's also
|
||||
# customary to leave one space after the ':'.
|
||||
|
||||
|-----handy-ruler------------------------------------------------------|
|
||||
php81: php81 (HTML-embedded scripting language)
|
||||
php81:
|
||||
php81: PHP is an HTML-embedded scripting language. It shares syntax
|
||||
php81: characteristics with C, Java, and Perl. The primary objective behind
|
||||
php81: this language is to make a fast and easy-to-use scripting language
|
||||
php81: for dynamic web sites.
|
||||
php81:
|
||||
php81: Homepage: https://www.php.net/
|
||||
php81:
|
||||
php81:
|
||||
php81:
|
@ -1,7 +0,0 @@
|
||||
PHP is an HTML-embedded scripting language. It shares syntax
|
||||
characteristics with C, Java, and Perl. The primary objective behind
|
||||
this language is to make a fast and easy-to-use scripting language for
|
||||
dynamic web sites.
|
||||
|
||||
This installation is compatible with the official php package and
|
||||
doesn't overwrit any stock files.
|
@ -1,18 +0,0 @@
|
||||
config() {
|
||||
NEW="$1"
|
||||
OLD="`dirname $NEW`/`basename $NEW .new`"
|
||||
# If there's no config file by that name, mv it over:
|
||||
if [ ! -r $OLD ]; then
|
||||
mv $NEW $OLD
|
||||
elif [ "`cat $OLD | md5sum`" = "`cat $NEW | md5sum`" ]; then # toss the redundant copy
|
||||
rm $NEW
|
||||
fi
|
||||
# Otherwise, we leave the .new copy for the admin to consider...
|
||||
}
|
||||
# Keep same perms on rc.php-fpm.new:
|
||||
if [ -e etc/rc.d/rc.php-fpm-8.2 ]; then
|
||||
cp -a etc/rc.d/rc.php-fpm-8.2 etc/rc.d/rc.php-fpm-8.2.new.incoming
|
||||
cat etc/rc.d/rc.php-fpm-8.2.new > etc/rc.d/rc.php-fpm-8.2.new.incoming
|
||||
mv etc/rc.d/rc.php-fpm-8.2.new.incoming etc/rc.d/rc.php-fpm-8.2.new
|
||||
fi
|
||||
config etc/rc.d/rc.php-fpm-8.2.new
|
@ -1,221 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Build and package PHP FPM 8.2
|
||||
# Copyright 2022 Eugene Wissner, Germany, Dachau
|
||||
#
|
||||
# by: David Cantrell <david@slackware.com>
|
||||
# Modified for PHP 4-5 by volkerdi@slackware.com
|
||||
# Copyright 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2015, 2017, 2019, 2020, 2021 Patrick Volkerding, Sebeka, MN, USA
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use of this script, with or without modification, is
|
||||
# permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of this script must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
cd $(dirname $0) ; CWD=$(pwd)
|
||||
|
||||
PRGNAM=php82
|
||||
VERSION=${VERSION:-8.2.0}
|
||||
BUILD=${BUILD:-1}
|
||||
TAG=${TAG:-_SBo}
|
||||
PKGTYPE=${PKGTYPE:-tgz}
|
||||
|
||||
VERSION_SUFFIX=8.2
|
||||
|
||||
if [ -z "$ARCH" ]; then
|
||||
case "$( uname -m )" in
|
||||
i?86) ARCH=i586 ;;
|
||||
arm*) ARCH=arm ;;
|
||||
*) ARCH=$( uname -m ) ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# If the variable PRINT_PACKAGE_NAME is set, then this script will report what
|
||||
# the name of the created package would be, and then exit. This information
|
||||
# could be useful to other scripts.
|
||||
if [ ! -z "${PRINT_PACKAGE_NAME}" ]; then
|
||||
echo "$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TMP=${TMP:-/tmp}
|
||||
PKG=$TMP/package-$PRGNAM
|
||||
OUTPUT=${OUTPUT:-/tmp}
|
||||
|
||||
if [ "$ARCH" = "i586" ]; then
|
||||
SLKCFLAGS="-O2 -march=i586 -mtune=i686"
|
||||
LIBDIRSUFFIX=""
|
||||
elif [ "$ARCH" = "i686" ]; then
|
||||
SLKCFLAGS="-O2 -march=i686 -mtune=i686"
|
||||
LIBDIRSUFFIX=""
|
||||
elif [ "$ARCH" = "x86_64" ]; then
|
||||
SLKCFLAGS="-O2 -fPIC"
|
||||
LIBDIRSUFFIX="64"
|
||||
else
|
||||
SLKCFLAGS="-O2"
|
||||
LIBDIRSUFFIX=""
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
rm -rf $PKG
|
||||
mkdir -p $TMP $PKG $OUTPUT
|
||||
cd $TMP
|
||||
rm -rf php-$VERSION
|
||||
tar xvf $CWD/php-$VERSION.tar.xz
|
||||
cd php-$VERSION
|
||||
chown -R root:root .
|
||||
|
||||
# Sometimes they ship a few of these:
|
||||
find . -name "*.orig" -delete
|
||||
|
||||
find -L . \
|
||||
\( -perm 777 -o -perm 775 -o -perm 750 -o -perm 711 -o -perm 555 \
|
||||
-o -perm 511 \) -exec chmod 755 {} \; -o \
|
||||
\( -perm 666 -o -perm 664 -o -perm 640 -o -perm 600 -o -perm 444 \
|
||||
-o -perm 440 -o -perm 400 \) -exec chmod 644 {} \;
|
||||
|
||||
sed -i "s|build$|php/${VERSION_SUFFIX}/build|" scripts/Makefile.frag
|
||||
sed -i "s|build\"$|php/${VERSION_SUFFIX}/build\"|" scripts/phpize.in
|
||||
|
||||
EXTENSION_DIR=/usr/lib${LIBDIRSUFFIX}/php/${VERSION_SUFFIX}/extensions \
|
||||
CFLAGS="$SLKCFLAGS -DU_DEFINE_FALSE_AND_TRUE=1" \
|
||||
CXXFLAGS="$SLKCFLAGS -DU_USING_ICU_NAMESPACE=1 -DU_DEFINE_FALSE_AND_TRUE=1" \
|
||||
./configure \
|
||||
--prefix=/usr \
|
||||
--libdir=/usr/lib${LIBDIRSUFFIX} \
|
||||
--with-libdir=lib${LIBDIRSUFFIX} \
|
||||
--localstatedir=/var \
|
||||
--sysconfdir=/etc/php/${VERSION_SUFFIX} \
|
||||
--datarootdir=/usr/share \
|
||||
--datadir=/usr/share \
|
||||
--infodir=/usr/info \
|
||||
--mandir=/usr/man \
|
||||
--program-suffix=-$VERSION_SUFFIX \
|
||||
--without-apxs2 \
|
||||
--enable-fpm \
|
||||
--with-fpm-user=apache \
|
||||
--with-fpm-group=apache \
|
||||
--enable-zts \
|
||||
--enable-pcntl \
|
||||
--enable-mbregex \
|
||||
--enable-tokenizer=shared \
|
||||
--with-config-file-scan-dir=/etc/php/${VERSION_SUFFIX}/php.d \
|
||||
--with-config-file-path=/etc/php/${VERSION_SUFFIX} \
|
||||
--with-layout=PHP \
|
||||
--disable-sigchild \
|
||||
--with-libxml \
|
||||
--with-expat \
|
||||
--enable-simplexml \
|
||||
--enable-xmlreader=shared \
|
||||
--enable-dom=shared \
|
||||
--enable-filter \
|
||||
--disable-debug \
|
||||
--with-openssl=shared \
|
||||
--with-external-pcre \
|
||||
--with-zlib=shared,/usr \
|
||||
--enable-bcmath=shared \
|
||||
--with-bz2=shared,/usr \
|
||||
--enable-calendar=shared \
|
||||
--enable-ctype=shared \
|
||||
--with-curl=shared \
|
||||
--enable-dba=shared \
|
||||
--with-gdbm=/usr \
|
||||
--with-db4=/usr \
|
||||
--enable-exif=shared \
|
||||
--enable-ftp=shared \
|
||||
--enable-gd=shared \
|
||||
--with-external-gd \
|
||||
--with-jpeg \
|
||||
--with-xpm \
|
||||
--with-gettext=shared,/usr \
|
||||
--with-gmp=shared,/usr \
|
||||
--with-iconv=shared \
|
||||
--with-imap-ssl=/usr \
|
||||
--with-pdo-pgsql=shared,/usr/bin/pg_config \
|
||||
--with-pgsql=shared,/usr/bin/pg_config \
|
||||
--with-ldap=shared \
|
||||
--enable-mbstring=shared \
|
||||
--enable-mysqlnd=shared \
|
||||
--with-mysqli=shared,mysqlnd \
|
||||
--with-mysql-sock=/var/run/mysql/mysql.sock \
|
||||
--with-iodbc=shared,/usr \
|
||||
--enable-pdo=shared \
|
||||
--with-pdo-mysql=shared,mysqlnd \
|
||||
--with-pdo-sqlite=shared,/usr \
|
||||
--with-pdo-odbc=shared,iODBC,/usr \
|
||||
--with-pspell=shared,/usr \
|
||||
--with-enchant=shared,/usr \
|
||||
--enable-shmop=shared \
|
||||
--with-snmp=shared,/usr \
|
||||
--enable-soap=shared \
|
||||
--enable-sockets \
|
||||
--with-sqlite3=shared \
|
||||
--enable-sysvmsg \
|
||||
--enable-sysvsem \
|
||||
--enable-sysvshm \
|
||||
--with-xsl=shared,/usr \
|
||||
--with-zip=shared \
|
||||
--enable-intl=shared \
|
||||
--enable-opcache \
|
||||
--enable-shared=yes \
|
||||
--enable-static=no \
|
||||
--with-gnu-ld \
|
||||
--with-pic \
|
||||
--enable-phpdbg \
|
||||
--with-sodium \
|
||||
--with-password-argon2 \
|
||||
--without-readline \
|
||||
--with-libedit \
|
||||
--with-pear=/usr/lib${LIBDIRSUFFIX}/php/${VERSION_SUFFIX} \
|
||||
--includedir=/usr/include/php/${VERSION_SUFFIX} \
|
||||
--with-tidy=shared \
|
||||
--build=$ARCH-slackware-linux
|
||||
|
||||
make
|
||||
make install INSTALL_ROOT=$PKG
|
||||
|
||||
mkdir -p $PKG/etc/rc.d
|
||||
cp sapi/fpm/init.d.php-fpm $PKG/etc/rc.d/rc.php-fpm-${VERSION_SUFFIX}.new
|
||||
chmod 644 $PKG/etc/rc.d/rc.php-fpm-${VERSION_SUFFIX}.new
|
||||
|
||||
# Strip ELF objects.
|
||||
find $PKG | xargs file | grep -e "executable" -e "shared object" | grep ELF \
|
||||
| cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null
|
||||
|
||||
find $PKG/usr/man -type f -exec gzip -9 {} \;
|
||||
for i in $( find $PKG/usr/man -type l ) ; do ln -s $( readlink $i ).gz $i.gz ; rm $i ; done
|
||||
|
||||
# PHP sometimes puts junk in the root directory:
|
||||
( cd $PKG
|
||||
rm -rf .channels .depdb .depdblock .filemap .lock .registry
|
||||
)
|
||||
|
||||
rm -r $PKG/usr/share/fpm $PKG/usr/bin/pear $PKG/usr/bin/peardev
|
||||
mv $PKG/usr/bin/pecl $PKG/usr/bin/pecl-${VERSION_SUFFIX}
|
||||
|
||||
mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION
|
||||
cp -a \
|
||||
CODING_STANDARDS* CONTRIBUTING* EXTENSIONS* LICENSE* NEWS* README* UPGRADING* \
|
||||
$PKG/usr/doc/$PRGNAM-$VERSION
|
||||
cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild
|
||||
|
||||
mkdir -p $PKG/install
|
||||
cat $CWD/slack-desc > $PKG/install/slack-desc
|
||||
cat $CWD/doinst.sh > $PKG/install/doinst.sh
|
||||
|
||||
cd $PKG
|
||||
/sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE
|
@ -1,10 +0,0 @@
|
||||
PRGNAM="php82"
|
||||
VERSION="8.2.0"
|
||||
HOMEPAGE="https://www.php.net/"
|
||||
DOWNLOAD="https://www.php.net/distributions/php-8.2.0.tar.xz"
|
||||
MD5SUM="43302de3d2c064f2f23c9693a2f17aeb"
|
||||
DOWNLOAD_x86_64=""
|
||||
MD5SUM_x86_64=""
|
||||
REQUIRES="postgresql"
|
||||
MAINTAINER="Eugene Wissner"
|
||||
EMAIL="belka@caraus.de"
|
@ -1,19 +0,0 @@
|
||||
# HOW TO EDIT THIS FILE:
|
||||
# The "handy ruler" below makes it easier to edit a package description. Line
|
||||
# up the first '|' above the ':' following the base package name, and the '|'
|
||||
# on the right side marks the last column you can put a character in. You must
|
||||
# make exactly 11 lines for the formatting to be correct. It's also
|
||||
# customary to leave one space after the ':'.
|
||||
|
||||
|-----handy-ruler------------------------------------------------------|
|
||||
php82: php82 (HTML-embedded scripting language)
|
||||
php82:
|
||||
php82: PHP is an HTML-embedded scripting language. It shares syntax
|
||||
php82: characteristics with C, Java, and Perl. The primary objective behind
|
||||
php82: this language is to make a fast and easy-to-use scripting language
|
||||
php82: for dynamic web sites.
|
||||
php82:
|
||||
php82: Homepage: https://www.php.net/
|
||||
php82:
|
||||
php82:
|
||||
php82:
|
@ -1,9 +0,0 @@
|
||||
Ragel compiles executable finite state machines from regular
|
||||
languages. Ragel targets C, C++, Objective-C, D, Java and Ruby.
|
||||
Ragel state machines can not only recognize byte sequences as regular
|
||||
expression machines do, but can also execute code at arbitrary points
|
||||
in the recognition of a regular language. Code embedding is done using
|
||||
inline operators that do not disrupt the regular language syntax.
|
||||
|
||||
NOTE: before building this it's recommended to remove any previous
|
||||
version you might have installed.
|
@ -1,15 +0,0 @@
|
||||
--- a/configure.ac 2021-02-15 20:45:20.000000000 +0100
|
||||
+++ b/configure.ac 2021-02-21 17:59:13.593674832 +0100
|
||||
@@ -46,9 +46,9 @@
|
||||
COLM_WRAP="$withval/bin/colm-wrap"
|
||||
CPPFLAGS="-I$withval/include ${CPPFLAGS}"
|
||||
CPPFLAGS="-I$withval/include/aapl ${CPPFLAGS}"
|
||||
- LDFLAGS="-L$withval/lib ${LDFLAGS}"
|
||||
- LIBCOLM_LA="$withval/lib/libcolm.la"
|
||||
- LIBFSM_LA="$withval/lib/libfsm.la"
|
||||
+ LDFLAGS="-L$withval/lib64 ${LDFLAGS}"
|
||||
+ LIBCOLM_LA="$withval/lib64/libcolm.la"
|
||||
+ LIBFSM_LA="$withval/lib64/libfsm.la"
|
||||
COLM_SHARE="$withval/share"
|
||||
],
|
||||
[]
|
@ -1,119 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Slackware build script for ragel
|
||||
|
||||
# Copyright 2012-2019 Matteo Bernardini <ponce@slackbuilds.org>, Pisa, Italy
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use of this script, with or without modification, is
|
||||
# permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of this script must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# 20220308 bkw: Modified by SlackBuilds.org:
|
||||
# This build always fails if ragel is already installed. Add a check
|
||||
# to make it fail quickly, with a useful error message (instead of a
|
||||
# confusing link error, after compiling for several minutes).
|
||||
|
||||
cd $(dirname $0) ; CWD=$(pwd)
|
||||
|
||||
PRGNAM=ragel
|
||||
VERSION=${VERSION:-7.0.4}
|
||||
BUILD=${BUILD:-1}
|
||||
TAG=${TAG:-_SBo}
|
||||
PKGTYPE=${PKGTYPE:-tgz}
|
||||
|
||||
if [ -z "$ARCH" ]; then
|
||||
case "$( uname -m )" in
|
||||
i?86) ARCH=i586 ;;
|
||||
arm*) ARCH=arm ;;
|
||||
*) ARCH=$( uname -m ) ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ ! -z "${PRINT_PACKAGE_NAME}" ]; then
|
||||
echo "$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TMP=${TMP:-/tmp/SBo}
|
||||
PKG=$TMP/package-$PRGNAM
|
||||
OUTPUT=${OUTPUT:-/tmp}
|
||||
|
||||
if [ "$ARCH" = "i586" ]; then
|
||||
SLKCFLAGS="-O2 -march=i586 -mtune=i686"
|
||||
LIBDIRSUFFIX=""
|
||||
elif [ "$ARCH" = "i686" ]; then
|
||||
SLKCFLAGS="-O2 -march=i686 -mtune=i686"
|
||||
LIBDIRSUFFIX=""
|
||||
elif [ "$ARCH" = "x86_64" ]; then
|
||||
SLKCFLAGS="-O2 -fPIC"
|
||||
LIBDIRSUFFIX="64"
|
||||
else
|
||||
SLKCFLAGS="-O2"
|
||||
LIBDIRSUFFIX=""
|
||||
fi
|
||||
|
||||
DOCS="COPYING README"
|
||||
|
||||
set -e
|
||||
|
||||
rm -rf $PKG
|
||||
mkdir -p $TMP $PKG $OUTPUT
|
||||
cd $TMP
|
||||
|
||||
rm -rf $PRGNAM-$VERSION
|
||||
tar xvf $CWD/$PRGNAM-$VERSION.tar.gz
|
||||
cd $PRGNAM-$VERSION
|
||||
chown -R root:root .
|
||||
find -L . \
|
||||
\( -perm 777 -o -perm 775 -o -perm 750 -o -perm 711 -o -perm 555 \
|
||||
-o -perm 511 \) -exec chmod 755 {} \+ -o \
|
||||
\( -perm 666 -o -perm 664 -o -perm 640 -o -perm 600 -o -perm 444 \
|
||||
-o -perm 440 -o -perm 400 \) -exec chmod 644 {} \+
|
||||
|
||||
if [ "$LIBDIRSUFFIX" = "64" ]; then
|
||||
patch --verbose -p1 -i $CWD/lib64.patch
|
||||
fi
|
||||
|
||||
CFLAGS="$SLKCFLAGS" \
|
||||
CXXFLAGS="$SLKCFLAGS" \
|
||||
./configure \
|
||||
--prefix=/usr \
|
||||
--libdir=/usr/lib${LIBDIRSUFFIX} \
|
||||
--sysconfdir=/etc \
|
||||
--localstatedir=/var \
|
||||
--mandir=/usr/man \
|
||||
--docdir=/usr/doc/$PRGNAM-$VERSION \
|
||||
--disable-static \
|
||||
--with-colm=/usr \
|
||||
--disable-manual \
|
||||
--build=$ARCH-slackware-linux
|
||||
|
||||
make
|
||||
make install-strip DESTDIR=$PKG
|
||||
gzip -9 $PKG/usr/man/man*/*
|
||||
|
||||
mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION
|
||||
cp -a $DOCS $PKG/usr/doc/$PRGNAM-$VERSION
|
||||
cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild
|
||||
|
||||
rm -f $PKG/usr/lib*/*.la
|
||||
|
||||
mkdir -p $PKG/install
|
||||
cat $CWD/slack-desc > $PKG/install/slack-desc
|
||||
|
||||
cd $PKG
|
||||
/sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE
|
@ -1,10 +0,0 @@
|
||||
PRGNAM="ragel"
|
||||
VERSION="7.0.4"
|
||||
HOMEPAGE="https://www.colm.net/open-source/ragel/"
|
||||
DOWNLOAD="https://www.colm.net/files/ragel/ragel-7.0.4.tar.gz"
|
||||
MD5SUM="2ca4f5507c1923bcf9a7909baa8254d3"
|
||||
DOWNLOAD_x86_64=""
|
||||
MD5SUM_x86_64=""
|
||||
REQUIRES="colm kelbt"
|
||||
MAINTAINER="Matteo Bernardini"
|
||||
EMAIL="ponce@slackbuilds.org"
|
@ -1,19 +0,0 @@
|
||||
# HOW TO EDIT THIS FILE:
|
||||
# The "handy ruler" below makes it easier to edit a package description.
|
||||
# Line up the first '|' above the ':' following the base package name, and
|
||||
# the '|' on the right side marks the last column you can put a character in.
|
||||
# You must make exactly 11 lines for the formatting to be correct. It's also
|
||||
# customary to leave one space after the ':' except on otherwise blank lines.
|
||||
|
||||
|-----handy-ruler------------------------------------------------------|
|
||||
ragel: ragel (State Machine Compiler)
|
||||
ragel:
|
||||
ragel: Ragel compiles executable finite state machines from regular
|
||||
ragel: languages. Ragel targets C, C++, Objective-C, D, Java and Ruby.
|
||||
ragel: Ragel state machines can not only recognize byte sequences as regular
|
||||
ragel: expression machines do, but can also execute code at arbitrary points
|
||||
ragel: in the recognition of a regular language. Code embedding is done using
|
||||
ragel: inline operators that do not disrupt the regular language syntax.
|
||||
ragel:
|
||||
ragel: homepage: https://www.colm.net/open-source/ragel/
|
||||
ragel:
|
@ -1,83 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rake'
|
||||
require_relative '../lib/download'
|
||||
|
||||
module SlackBuilder
|
||||
module DmdTools
|
||||
extend Rake::FileUtilsExt
|
||||
|
||||
def self.update_dmd(version)
|
||||
tarball_name = "dmd.#{version}.linux.tar.xz"
|
||||
|
||||
uri = URI "http://downloads.dlang.org/releases/2.x/#{version}/#{tarball_name}"
|
||||
checksum = download(uri, "slackbuilds/development/dmd/#{tarball_name}")
|
||||
|
||||
package = Package.new 'development/dmd', version: version,
|
||||
homepage: 'https://dlang.org'
|
||||
|
||||
write_info package, downloads: [Download.new(uri.to_s, checksum.hexdigest)]
|
||||
|
||||
update_slackbuild_version 'development/dmd', package.version
|
||||
commit 'development/dmd', version
|
||||
end
|
||||
|
||||
def self.update_tools(version, dub_version, dscanner_version, dcd_version)
|
||||
checksum = collect_checksums(version, dub_version, dscanner_version, dcd_version)
|
||||
|
||||
package = Package.new 'development/d-tools',
|
||||
version: version,
|
||||
homepage: 'https://dlang.org',
|
||||
requires: ['dmd']
|
||||
|
||||
write_tools_info package, dub_version, dscanner_version, dcd_version, checksum
|
||||
update_tools_versions dub_version, dscanner_version, dcd_version
|
||||
|
||||
update_slackbuild_version 'development/d-tools', package.version
|
||||
commit 'development/d-tools', package.version
|
||||
end
|
||||
|
||||
private_class_method def self.write_tools_info(package, dub_version, dscanner_version, dcd_version, checksum)
|
||||
write_info package,
|
||||
downloads: [
|
||||
Download.new(hosted_sources("/d-tools/dub-#{dub_version}.tar.gz"), checksum[:dub]),
|
||||
Download.new(hosted_sources("/d-tools/tools-#{package.version}.tar.gz"), checksum[:tools]),
|
||||
Download.new(hosted_sources("/d-tools/D-Scanner-#{dscanner_version}.tar.xz"), checksum[:dscanner]),
|
||||
Download.new(hosted_sources("/d-tools/DCD-#{dcd_version}.tar.xz"), checksum[:dcd])
|
||||
]
|
||||
end
|
||||
|
||||
private_class_method def self.collect_checksums(version, dub_version, dscanner_version, dcd_version)
|
||||
checksum = {}
|
||||
|
||||
uri = URI "https://codeload.github.com/dlang/tools/tar.gz/v#{version}"
|
||||
checksum[:tools] = download_and_deploy uri, "development/d-tools/tools-#{version}.tar.gz"
|
||||
|
||||
uri = URI "https://codeload.github.com/dlang/dub/tar.gz/v#{dub_version}"
|
||||
checksum[:dub] = download_and_deploy uri, "development/d-tools/dub-#{dub_version}.tar.gz"
|
||||
|
||||
checksum[:dscanner] = clone 'https://github.com/dlang-community/D-Scanner.git',
|
||||
"development/d-tools/D-Scanner-#{dscanner_version}.tar.xz"
|
||||
checksum[:dcd] = clone 'https://github.com/dlang-community/DCD.git',
|
||||
"development/d-tools/DCD-#{dcd_version}.tar.xz"
|
||||
|
||||
checksum
|
||||
end
|
||||
|
||||
private_class_method def self.update_tools_versions(dub_version, dscanner_version, dcd_version)
|
||||
slackbuild_filename = 'slackbuilds/development/d-tools/d-tools.SlackBuild'
|
||||
slackbuild_contents = File.read(slackbuild_filename)
|
||||
.gsub(/^DUB_VERSION=\${DUB_VERSION:-.+/,
|
||||
"DUB_VERSION=${DUB_VERSION:-#{dub_version}}")
|
||||
.gsub(/^DSCANNER_VERSION=\${DSCANNER_VERSION:-.+/,
|
||||
"DSCANNER_VERSION=${DSCANNER_VERSION:-#{dscanner_version}}")
|
||||
.gsub(/^DCD_VERSION=\${DCD_VERSION:-.+/,
|
||||
"DCD_VERSION=${DCD_VERSION:-#{dcd_version}}")
|
||||
File.open(slackbuild_filename, 'w') { |file| file.puts slackbuild_contents }
|
||||
end
|
||||
end
|
||||
end
|
@ -1,67 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
# frozen_string_literal: true
|
||||
|
||||
namespace :hhvm do
|
||||
desc 'Generates diffs with removed download URLs'
|
||||
task :bundled_dependencies, [:version] do |_, arguments|
|
||||
run_on_source arguments[:version] do |third_party|
|
||||
c_make_lists = third_party + 'CMakeLists.txt'
|
||||
next unless c_make_lists.exist?
|
||||
|
||||
contents = c_make_lists.read
|
||||
set_hhvm_start = contents.index 'SET_HHVM_THIRD_PARTY_SOURCE_ARGS('
|
||||
next if set_hhvm_start.nil?
|
||||
|
||||
line = contents[..set_hhvm_start].count "\n"
|
||||
in_lines = contents.lines
|
||||
4.times { in_lines.delete_at(line + 2) }
|
||||
|
||||
puts Open3.capture2('diff', '-Nur', c_make_lists.to_path, '-', stdin_data: in_lines.join).first
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Generated SlackBuild code to prepare bundled dependencies'
|
||||
task :bundled_code, [:version] do |_, arguments|
|
||||
run_on_source arguments[:version] do |third_party|
|
||||
c_make_lists = third_party + 'CMakeLists.txt'
|
||||
next unless c_make_lists.exist?
|
||||
|
||||
contents = c_make_lists.read
|
||||
set_hhvm_start = contents.index 'SET_HHVM_THIRD_PARTY_SOURCE_ARGS('
|
||||
next if set_hhvm_start.nil?
|
||||
|
||||
set_hhvm_end = contents.index ')', set_hhvm_start
|
||||
set_hhvm_start += 'SET_HHVM_THIRD_PARTY_SOURCE_ARGS('.length
|
||||
set_hhvm_end -= 1
|
||||
contents = contents[set_hhvm_start..set_hhvm_end].split[1..].map(&:strip)
|
||||
|
||||
src = Pathname.new('third-party') +
|
||||
third_party.basename +
|
||||
"bundled_#{third_party.basename}-prefix" + 'src'
|
||||
bundled = src + "bundled_#{third_party.basename}"
|
||||
archive_name = contents[1][contents[1].rindex('/') + 1..-2]
|
||||
|
||||
puts "mkdir -p #{bundled}"
|
||||
puts "install -m 0644 -D $CWD/#{archive_name} #{src + archive_name}"
|
||||
puts "tar -zxvf $CWD/#{archive_name} -C #{bundled}"
|
||||
puts
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def run_on_source(version, &block)
|
||||
package = Package.new 'development/hhvm',
|
||||
version: version,
|
||||
homepage: 'https://hhvm.com/',
|
||||
requires: %w[tbb glog libdwarf libmemcached dobule-conversion]
|
||||
repository = SlackBuilder.clone 'https://github.com/facebook/hhvm.git', package, 'HHVM-'
|
||||
|
||||
(repository + 'third-party').each_child do |third_party|
|
||||
block.call third_party
|
||||
end
|
||||
end
|
107
slackbuilder.cabal
Normal file
107
slackbuilder.cabal
Normal file
@ -0,0 +1,107 @@
|
||||
cabal-version: 2.4
|
||||
name: slackbuilder
|
||||
version: 1.0
|
||||
|
||||
synopsis: Tool to automatically update Slackware build scripts.
|
||||
bug-reports: https://git.caraus.tech/OSS/slackbuilder/issues
|
||||
|
||||
license: MPL-2.0
|
||||
license-files: LICENSE
|
||||
copyright: (c) 2023-2025 Eugen Wissner
|
||||
|
||||
author: Eugen Wissner
|
||||
maintainer: belka@caraus.de
|
||||
|
||||
category: Build
|
||||
extra-source-files:
|
||||
CHANGELOG.md
|
||||
README.md
|
||||
|
||||
source-repository head
|
||||
type: git
|
||||
location: https://git.caraus.tech/OSS/slackbuilder.git
|
||||
|
||||
common dependencies
|
||||
build-depends:
|
||||
aeson ^>= 2.2.0,
|
||||
base >= 4.16 && < 5,
|
||||
bytestring ^>= 0.12.0,
|
||||
conduit ^>= 1.3.5,
|
||||
conduit-extra ^>= 1.3,
|
||||
http-client ^>= 0.7,
|
||||
http-client-tls ^>= 0.3,
|
||||
containers ^>= 0.7,
|
||||
crypton ^>= 1.0,
|
||||
directory ^>= 1.3.8,
|
||||
exceptions >= 0.10,
|
||||
filepath ^>= 1.5,
|
||||
http-types ^>= 0.12.4,
|
||||
megaparsec ^>= 9.7,
|
||||
modern-uri ^>= 0.3.6,
|
||||
memory ^>= 0.18,
|
||||
parser-combinators ^>= 1.3,
|
||||
process ^>= 1.6.18,
|
||||
req ^>= 3.13,
|
||||
tar-conduit ^>= 0.4,
|
||||
lzma ^>= 0.0.1,
|
||||
text ^>= 2.1,
|
||||
tomland ^>= 1.3.3,
|
||||
transformers ^>= 0.6.1,
|
||||
unordered-containers ^>= 0.2.20,
|
||||
vector ^>= 0.13.0,
|
||||
word8 ^>= 0.1.3
|
||||
default-language: GHC2024
|
||||
default-extensions:
|
||||
DuplicateRecordFields
|
||||
OverloadedStrings
|
||||
RecordWildCards
|
||||
QuasiQuotes
|
||||
TemplateHaskell
|
||||
|
||||
library
|
||||
import: dependencies
|
||||
exposed-modules:
|
||||
SlackBuilder.Config
|
||||
SlackBuilder.Download
|
||||
SlackBuilder.Info
|
||||
SlackBuilder.LatestVersionCheck
|
||||
SlackBuilder.Package
|
||||
SlackBuilder.Trans
|
||||
hs-source-dirs: lib
|
||||
ghc-options: -Wall
|
||||
build-depends:
|
||||
mono-traversable ^>= 1.0.17
|
||||
|
||||
executable slackbuilder
|
||||
import: dependencies
|
||||
main-is: Main.hs
|
||||
|
||||
other-modules:
|
||||
SlackBuilder.CommandLine
|
||||
SlackBuilder.Update
|
||||
build-depends:
|
||||
ansi-terminal ^>= 1.1,
|
||||
optparse-applicative ^>= 0.18.1,
|
||||
slackbuilder
|
||||
hs-source-dirs: src
|
||||
|
||||
ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall
|
||||
|
||||
test-suite slackbuilder-test
|
||||
import: dependencies
|
||||
type: exitcode-stdio-1.0
|
||||
main-is: Spec.hs
|
||||
|
||||
other-modules:
|
||||
SlackBuilder.InfoSpec
|
||||
SlackBuilder.LatestVersionCheckSpec
|
||||
SlackBuilder.PackageSpec
|
||||
hs-source-dirs: tests
|
||||
build-depends:
|
||||
hspec >= 2.10.9 && < 2.12,
|
||||
hspec-megaparsec ^>= 2.2,
|
||||
slackbuilder
|
||||
|
||||
ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall
|
||||
build-tool-depends:
|
||||
hspec-discover:hspec-discover
|
118
src/Main.hs
Normal file
118
src/Main.hs
Normal file
@ -0,0 +1,118 @@
|
||||
{- This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||
v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
obtain one at https://mozilla.org/MPL/2.0/. -}
|
||||
|
||||
module Main
|
||||
( main
|
||||
) where
|
||||
|
||||
import Control.Monad.Catch (MonadThrow(..))
|
||||
import Control.Monad.IO.Class (MonadIO(..))
|
||||
import qualified Data.Map as Map
|
||||
import Options.Applicative (execParser)
|
||||
import SlackBuilder.CommandLine
|
||||
import SlackBuilder.Config
|
||||
import SlackBuilder.Trans
|
||||
import SlackBuilder.LatestVersionCheck
|
||||
import SlackBuilder.Update
|
||||
import qualified Toml
|
||||
import Data.Text (Text)
|
||||
import qualified Data.Text.IO as Text
|
||||
import Control.Monad.Trans.Reader (ReaderT(..), asks)
|
||||
import SlackBuilder.Package (PackageDescription(..), renderTextWithVersion)
|
||||
import qualified SlackBuilder.Package as Package
|
||||
import Data.Foldable (find, traverse_)
|
||||
import GHC.Records (HasField(..))
|
||||
import System.Console.ANSI
|
||||
( setSGR
|
||||
, SGR(..)
|
||||
, ColorIntensity(..)
|
||||
, Color(..)
|
||||
, ConsoleLayer(..)
|
||||
)
|
||||
import Data.Maybe (mapMaybe)
|
||||
import qualified Text.URI as URI
|
||||
|
||||
autoUpdatable :: [PackageSettings] -> [PackageDescription]
|
||||
autoUpdatable = mapMaybe go
|
||||
where
|
||||
go PackageSettings{ downloader = setting, downloaders } = do
|
||||
latest' <- packageUpdaterFromSettings setting
|
||||
pure $ PackageDescription
|
||||
{ latest = latest'
|
||||
, name = getField @"name" setting
|
||||
, downloaders = Map.fromList $ mapMaybe forDownloader downloaders
|
||||
}
|
||||
forDownloader downloaderSettings@DownloaderSettings{ name } =
|
||||
(name,) <$> packageUpdaterFromSettings downloaderSettings
|
||||
|
||||
packageUpdaterFromSettings :: DownloaderSettings -> Maybe Package.Updater
|
||||
packageUpdaterFromSettings DownloaderSettings{..} = do
|
||||
getVersion' <- getVersionSettings
|
||||
detectLatest' <- detectLatestSettings
|
||||
Just Package.Updater
|
||||
{ detectLatest = detectLatest'
|
||||
, getVersion = getVersion'
|
||||
, is64 = is64
|
||||
}
|
||||
where
|
||||
detectLatestSettings
|
||||
| Just githubSettings <- github =
|
||||
let ghArguments = uncurry PackageOwner githubSettings
|
||||
in Just $ latestGitHub ghArguments version
|
||||
| Just packagistSettings <- packagist =
|
||||
let packagistArguments = uncurry PackageOwner packagistSettings
|
||||
in Just $ latestPackagist packagistArguments
|
||||
| Just textSettings <- text =
|
||||
let textArguments = uncurry TextArguments textSettings
|
||||
in Just $ latestText textArguments version
|
||||
| otherwise = Nothing
|
||||
getVersionSettings
|
||||
| Just template' <- template =
|
||||
Just $ repackageWithTemplate repackage $ Package.DownloadTemplate template'
|
||||
| Just CloneSettings{..} <- clone
|
||||
= flip cloneFromGit (renderTextWithVersion tagTemplate version)
|
||||
<$> URI.mkURI remote
|
||||
| otherwise = Nothing
|
||||
|
||||
up2Date :: Maybe Text -> SlackBuilderT ()
|
||||
up2Date selectedPackage = do
|
||||
packages' <- SlackBuilderT $ asks (getField @"packages")
|
||||
case selectedPackage of
|
||||
Nothing -> traverse_ (handleExceptions . go) $ autoUpdatable packages'
|
||||
Just packageName
|
||||
| Just foundPackage <- find ((packageName ==) . getField @"name") (autoUpdatable packages') ->
|
||||
go foundPackage
|
||||
| otherwise -> throwM $ UpdaterNotFound packageName
|
||||
where
|
||||
go package = getAndLogLatest package
|
||||
>>= mapM_ updatePackageIfRequired
|
||||
>> liftIO (putStrLn "")
|
||||
|
||||
check :: SlackBuilderT ()
|
||||
check = SlackBuilderT (asks (getField @"packages"))
|
||||
>>= traverse_ (handleExceptions . go) . autoUpdatable
|
||||
where
|
||||
go package = getAndLogLatest package
|
||||
>>= mapM_ checkUpdateAvailability
|
||||
>> liftIO (putStrLn "")
|
||||
|
||||
main :: IO ()
|
||||
main = execParser slackBuilderParser
|
||||
>>= handleExceptions . withCommandLine
|
||||
where
|
||||
withCommandLine programCommand = do
|
||||
settingsResult <- Toml.decodeFileEither settingsCodec configurationFile
|
||||
case settingsResult of
|
||||
Right settings -> flip runReaderT settings
|
||||
$ runSlackBuilderT
|
||||
$ executeCommand programCommand
|
||||
Left settingsErrors
|
||||
-> setSGR [SetColor Foreground Dull Red]
|
||||
>> putStrLn (configurationFile <> " parsing failed.")
|
||||
>> setSGR [Reset]
|
||||
>> Text.putStr (Toml.prettyTomlDecodeErrors settingsErrors)
|
||||
configurationFile = "config/config.toml"
|
||||
executeCommand = \case
|
||||
CheckCommand -> check
|
||||
Up2DateCommand packageName -> up2Date packageName
|
43
src/SlackBuilder/CommandLine.hs
Normal file
43
src/SlackBuilder/CommandLine.hs
Normal file
@ -0,0 +1,43 @@
|
||||
{- This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||
v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
obtain one at https://mozilla.org/MPL/2.0/. -}
|
||||
|
||||
-- | Command line parser.
|
||||
module SlackBuilder.CommandLine
|
||||
( SlackBuilderCommand(..)
|
||||
, slackBuilderParser
|
||||
) where
|
||||
|
||||
import Data.Text (Text)
|
||||
import Options.Applicative
|
||||
( Parser
|
||||
, ParserInfo(..)
|
||||
, metavar
|
||||
, argument
|
||||
, helper
|
||||
, str
|
||||
, info
|
||||
, fullDesc
|
||||
, subparser
|
||||
, command
|
||||
, optional, progDesc
|
||||
)
|
||||
|
||||
data SlackBuilderCommand
|
||||
= CheckCommand
|
||||
| Up2DateCommand (Maybe Text)
|
||||
|
||||
slackBuilderParser :: ParserInfo SlackBuilderCommand
|
||||
slackBuilderParser = info (helper <*> slackBuilderCommand) fullDesc
|
||||
|
||||
slackBuilderCommand :: Parser SlackBuilderCommand
|
||||
slackBuilderCommand = subparser
|
||||
$ command "check" checkCommand
|
||||
<> command "up2date" up2DateCommand
|
||||
where
|
||||
checkCommand = info checkP $ progDesc "Check all configured slackbuilds for updates"
|
||||
checkP = pure CheckCommand
|
||||
up2DateP = Up2DateCommand
|
||||
<$> optional (argument str (metavar "PKGNAM"))
|
||||
up2DateCommand = info up2DateP
|
||||
$ progDesc "Update a single or multiple slackbuild in the configured repository"
|
333
src/SlackBuilder/Update.hs
Normal file
333
src/SlackBuilder/Update.hs
Normal file
@ -0,0 +1,333 @@
|
||||
{- This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||
v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
obtain one at https://mozilla.org/MPL/2.0/. -}
|
||||
|
||||
module SlackBuilder.Update
|
||||
( checkUpdateAvailability
|
||||
, cloneFromGit
|
||||
, downloadWithTemplate
|
||||
, getAndLogLatest
|
||||
, handleExceptions
|
||||
, listRepository
|
||||
, repackageWithTemplate
|
||||
, reuploadWithTemplate
|
||||
, updatePackageIfRequired
|
||||
) where
|
||||
|
||||
import Control.Exception (Exception(..), SomeException(..))
|
||||
import Control.Monad.Catch (MonadCatch(..), catches, Handler(..))
|
||||
import Control.Monad.IO.Class (MonadIO(..))
|
||||
import Control.Monad.Trans.Reader (asks)
|
||||
import qualified Data.ByteString.Char8 as Char8
|
||||
import Data.Foldable (Foldable(..), find)
|
||||
import Data.HashMap.Strict (HashMap)
|
||||
import qualified Data.HashMap.Strict as HashMap
|
||||
import qualified Data.List.NonEmpty as NonEmpty
|
||||
import Data.Maybe (fromJust, fromMaybe)
|
||||
import Data.Text (Text)
|
||||
import qualified Data.Text as Text
|
||||
import qualified Data.Text.IO as Text.IO
|
||||
import GHC.Records (HasField(..))
|
||||
import qualified Network.HTTP.Req as Req
|
||||
import Network.HTTP.Client (HttpException(..), HttpExceptionContent(..), responseStatus)
|
||||
import System.FilePath
|
||||
( (</>)
|
||||
, (<.>)
|
||||
, dropExtension
|
||||
, takeBaseName
|
||||
, splitFileName
|
||||
, takeDirectory
|
||||
, takeFileName
|
||||
, dropTrailingPathSeparator
|
||||
)
|
||||
import System.Process
|
||||
( CmdSpec(..)
|
||||
, CreateProcess(..)
|
||||
, StdStream(..)
|
||||
, withCreateProcess
|
||||
, waitForProcess
|
||||
)
|
||||
import SlackBuilder.Config
|
||||
import SlackBuilder.Download
|
||||
import SlackBuilder.Info
|
||||
import SlackBuilder.Package (PackageDescription(..), PackageUpdateData(..))
|
||||
import qualified SlackBuilder.Package as Package
|
||||
import SlackBuilder.Trans
|
||||
import Text.URI (URI(..))
|
||||
import qualified Text.URI as URI
|
||||
import System.Directory
|
||||
( listDirectory
|
||||
, doesDirectoryExist
|
||||
, withCurrentDirectory
|
||||
, removeDirectoryRecursive
|
||||
)
|
||||
import System.Console.ANSI
|
||||
( setSGR
|
||||
, SGR(..)
|
||||
, ColorIntensity(..)
|
||||
, Color(..)
|
||||
, ConsoleLayer(..)
|
||||
)
|
||||
import Control.Monad (filterM, void)
|
||||
import Data.List (isPrefixOf, isSuffixOf, partition)
|
||||
import Data.Functor ((<&>))
|
||||
import Data.Bifunctor (Bifunctor(..))
|
||||
import Network.HTTP.Types (Status(..))
|
||||
|
||||
getAndLogLatest :: PackageDescription -> SlackBuilderT (Maybe PackageUpdateData)
|
||||
getAndLogLatest description = do
|
||||
let PackageDescription{ latest = Package.Updater{ detectLatest }, name } = description
|
||||
liftIO (putStrLn $ Text.unpack name <> ": Retreiving the latest version.")
|
||||
detectedVersion <- detectLatest
|
||||
category <- HashMap.lookup name <$> listRepository
|
||||
pure $ PackageUpdateData description
|
||||
<$> category
|
||||
<*> detectedVersion
|
||||
|
||||
checkUpdateAvailability :: PackageUpdateData -> SlackBuilderT (Maybe PackageInfo)
|
||||
checkUpdateAvailability PackageUpdateData{..} = do
|
||||
parsedInfoFile <- readInfoFile category $ getField @"name" description
|
||||
|
||||
if version == getField @"version" parsedInfoFile
|
||||
then liftIO $ do
|
||||
setSGR [SetColor Foreground Dull Green]
|
||||
Text.IO.putStrLn
|
||||
$ getField @"name" description <> " is up to date (Version " <> version <> ")."
|
||||
setSGR [Reset]
|
||||
pure Nothing
|
||||
else liftIO $ do
|
||||
setSGR [SetColor Foreground Dull Yellow]
|
||||
Text.IO.putStr
|
||||
$ "A new version of "
|
||||
<> getField @"name" description
|
||||
<> " " <> getField @"version" parsedInfoFile
|
||||
<> " is available (" <> version <> ")."
|
||||
setSGR [Reset]
|
||||
putStrLn ""
|
||||
pure $ Just parsedInfoFile
|
||||
|
||||
updatePackageIfRequired :: PackageUpdateData -> SlackBuilderT ()
|
||||
updatePackageIfRequired updateData
|
||||
= checkUpdateAvailability updateData
|
||||
>>= mapM_ (updatePackage updateData)
|
||||
|
||||
data DownloadUpdated = DownloadUpdated
|
||||
{ result :: Package.Download
|
||||
, version :: Text
|
||||
, is64 :: Bool
|
||||
} deriving (Eq, Show)
|
||||
|
||||
updateDownload :: Text -> Package.Updater -> SlackBuilderT DownloadUpdated
|
||||
updateDownload packagePath Package.Updater{..} = do
|
||||
latestDownloadVersion <- fromJust <$> detectLatest
|
||||
result <- getVersion packagePath latestDownloadVersion
|
||||
pure $ DownloadUpdated
|
||||
{ result = result
|
||||
, version = latestDownloadVersion
|
||||
, is64 = is64
|
||||
}
|
||||
|
||||
cloneFromGit :: URI -> Text -> Text -> Text -> SlackBuilderT Package.Download
|
||||
cloneFromGit repo tagPrefix packagePath version = do
|
||||
let downloadFileName = URI.unRText
|
||||
$ NonEmpty.last $ snd $ fromJust $ URI.uriPath repo
|
||||
relativeTarball = Text.unpack packagePath
|
||||
</> (dropExtension (Text.unpack downloadFileName) <> "-" <> Text.unpack version)
|
||||
(uri', checksum) <- cloneAndUpload (URI.render repo) relativeTarball tagPrefix
|
||||
pure $ Package.Download
|
||||
{ md5sum = checksum
|
||||
, download = uri'
|
||||
}
|
||||
|
||||
repackageWithTemplate :: Maybe [String] -> Package.DownloadTemplate -> Text -> Text -> SlackBuilderT Package.Download
|
||||
repackageWithTemplate Nothing template' = downloadWithTemplate template'
|
||||
repackageWithTemplate (Just (cmd : arguments)) template' =
|
||||
reuploadWithTemplate' template' (RawCommand cmd arguments)
|
||||
repackageWithTemplate (Just []) template' = reuploadWithTemplate template'
|
||||
|
||||
downloadWithTemplate :: Package.DownloadTemplate -> Text -> Text -> SlackBuilderT Package.Download
|
||||
downloadWithTemplate downloadTemplate packagePath version = do
|
||||
repository' <- SlackBuilderT $ asks repository
|
||||
uri' <- liftIO $ Package.renderDownloadWithVersion downloadTemplate version
|
||||
checksum <- download uri' $ repository' </> Text.unpack packagePath
|
||||
pure $ Package.Download uri' $ snd checksum
|
||||
|
||||
reuploadWithTemplate :: Package.DownloadTemplate -> Text -> Text -> SlackBuilderT Package.Download
|
||||
reuploadWithTemplate downloadTemplate packagePath version = do
|
||||
repository' <- SlackBuilderT $ asks repository
|
||||
uri' <- liftIO $ Package.renderDownloadWithVersion downloadTemplate version
|
||||
let packagePathRelativeToCurrent = repository' </> Text.unpack packagePath
|
||||
(downloadedFileName, checksum) <- download uri' packagePathRelativeToCurrent
|
||||
|
||||
download' <- handleReupload packagePath
|
||||
$ packagePathRelativeToCurrent </> downloadedFileName
|
||||
pure $ Package.Download download' checksum
|
||||
|
||||
reuploadWithTemplate' :: Package.DownloadTemplate -> CmdSpec -> Text -> Text -> SlackBuilderT Package.Download
|
||||
reuploadWithTemplate' downloadTemplate commands packagePath version = do
|
||||
repository' <- SlackBuilderT $ asks repository
|
||||
uri' <- liftIO $ Package.renderDownloadWithVersion downloadTemplate version
|
||||
let downloadFileName = Text.unpack
|
||||
$ URI.unRText
|
||||
$ NonEmpty.last $ snd $ fromJust $ URI.uriPath uri'
|
||||
packagePathRelativeToCurrent = repository' </> Text.unpack packagePath
|
||||
|
||||
changedArchiveRootName <- extractRemote uri' packagePathRelativeToCurrent
|
||||
let relativeTarball = packagePathRelativeToCurrent
|
||||
</> fromMaybe downloadFileName changedArchiveRootName
|
||||
(relativeTarball', checksum) <- prepareSource relativeTarball
|
||||
|
||||
download' <- handleReupload packagePath relativeTarball'
|
||||
pure $ Package.Download download' checksum
|
||||
where
|
||||
prepareSource tarballPath =
|
||||
liftIO (defaultCreateProcess tarballPath commands)
|
||||
>> liftIO (tarCompress tarballPath)
|
||||
<* liftIO (removeDirectoryRecursive tarballPath)
|
||||
tarCompress tarballPath =
|
||||
let archiveBaseFilename = takeFileName tarballPath
|
||||
appendTarExtension = (<.> "tar.xz")
|
||||
in fmap (appendTarExtension tarballPath,)
|
||||
$ withCurrentDirectory (takeDirectory tarballPath)
|
||||
$ createLzmaTarball archiveBaseFilename (appendTarExtension archiveBaseFilename)
|
||||
defaultCreateProcess cwd' cmdSpec
|
||||
= flip withCreateProcess (const . const . const waitForProcess)
|
||||
$ CreateProcess
|
||||
{ use_process_jobs = False
|
||||
, std_out = Inherit
|
||||
, std_in = NoStream
|
||||
, std_err = Inherit
|
||||
, new_session = False
|
||||
, env = Nothing
|
||||
, detach_console = False
|
||||
, delegate_ctlc = False
|
||||
, cwd = Just cwd'
|
||||
, create_new_console = False
|
||||
, create_group = False
|
||||
, cmdspec = cmdSpec
|
||||
, close_fds = True
|
||||
, child_user = Nothing
|
||||
, child_group = Nothing
|
||||
}
|
||||
|
||||
handleReupload :: Text -> String -> SlackBuilderT URI
|
||||
handleReupload packagePath relativeTarball = do
|
||||
liftIO $ putStrLn $ "Upload the source tarball " <> relativeTarball
|
||||
uploadSource relativeTarball category'
|
||||
|
||||
hostedSources $ NonEmpty.cons category'
|
||||
$ pure $ Text.pack $ takeFileName relativeTarball
|
||||
where
|
||||
category' = Text.pack $ takeBaseName $ Text.unpack packagePath
|
||||
|
||||
updatePackage :: PackageUpdateData -> PackageInfo -> SlackBuilderT ()
|
||||
updatePackage PackageUpdateData{..} info = do
|
||||
let packagePath = category <> "/" <> getField @"name" description
|
||||
latest' = getField @"latest" description
|
||||
|
||||
repository' <- SlackBuilderT $ asks repository
|
||||
mainDownload <- (, getField @"is64" latest')
|
||||
<$> getField @"getVersion" latest' packagePath version
|
||||
moreDownloads <- traverse (updateDownload packagePath)
|
||||
$ getField @"downloaders" description
|
||||
let (downloads64, allDownloads) = partition snd
|
||||
$ mainDownload
|
||||
: (liftA2 (,) (getField @"result") (getField @"is64") <$> toList moreDownloads)
|
||||
let infoFilePath = repository' </> Text.unpack packagePath
|
||||
</> (Text.unpack (getField @"name" description) <.> "info")
|
||||
package' = info
|
||||
{ version = version
|
||||
, downloads = getField @"download" . fst <$> allDownloads
|
||||
, checksums = getField @"md5sum" . fst <$> allDownloads
|
||||
, downloadX64 = getField @"download" . fst <$> downloads64
|
||||
, checksumX64 = getField @"md5sum" . fst <$> downloads64
|
||||
}
|
||||
liftIO $ Text.IO.writeFile infoFilePath $ generate package'
|
||||
updateSlackBuildVersion packagePath version
|
||||
$ getField @"version" <$> moreDownloads
|
||||
|
||||
commit packagePath version
|
||||
|
||||
listRepository :: SlackBuilderT (HashMap Text Text)
|
||||
listRepository = do
|
||||
repository' <- SlackBuilderT $ asks repository
|
||||
listing <- go repository' [] ""
|
||||
pure $ HashMap.fromList $ bimap Text.pack Text.pack <$> listing
|
||||
where
|
||||
go currentDirectory found accumulatedDirectory = do
|
||||
let fullDirectory = currentDirectory </> accumulatedDirectory
|
||||
contents <- liftIO $ listDirectory fullDirectory
|
||||
case find (isSuffixOf ".info") contents of
|
||||
Just _ ->
|
||||
let (category, packageName) = first dropTrailingPathSeparator
|
||||
$ splitFileName accumulatedDirectory
|
||||
in pure $ (packageName, category) : found
|
||||
Nothing ->
|
||||
let accumulatedDirectories = (accumulatedDirectory </>)
|
||||
<$> filter (not . isPrefixOf ".") contents
|
||||
directoryFilter = liftIO . doesDirectoryExist
|
||||
. (currentDirectory </>)
|
||||
in filterM directoryFilter accumulatedDirectories
|
||||
>>= traverse (go currentDirectory found) <&> concat
|
||||
|
||||
handleExceptions :: (MonadIO m, MonadCatch m) => forall a. m a -> m ()
|
||||
handleExceptions action = catches (void action)
|
||||
[ Handler handleHttp
|
||||
, Handler handleSome
|
||||
]
|
||||
where
|
||||
printException e
|
||||
= liftIO (setSGR [SetColor Foreground Dull Red])
|
||||
>> liftIO (putStrLn e)
|
||||
>> liftIO (setSGR [Reset])
|
||||
showStatus (Status code message) =
|
||||
Char8.pack (show code) <> " \"" <> message <> "\""
|
||||
showHttpExceptionContent (StatusCodeException response _) = Char8.unpack
|
||||
$ "The server returned "
|
||||
<> showStatus (responseStatus response)
|
||||
<> " response status code."
|
||||
showHttpExceptionContent (TooManyRedirects _) =
|
||||
"The server responded with too many redirects for a request."
|
||||
showHttpExceptionContent OverlongHeaders = "Too many total bytes in the HTTP header were returned by the server."
|
||||
showHttpExceptionContent TooManyHeaderFields = "Too many HTTP header fields were returned by the server."
|
||||
showHttpExceptionContent ResponseTimeout = "The server took too long to return a response."
|
||||
showHttpExceptionContent ConnectionTimeout = "Attempting to connect to the server timed out"
|
||||
showHttpExceptionContent (ConnectionFailure connectionException) = displayException connectionException
|
||||
showHttpExceptionContent (InvalidStatusLine statusLine) = Char8.unpack
|
||||
$ "The status line returned by the server could not be parsed: "
|
||||
<> statusLine <> "."
|
||||
showHttpExceptionContent (InvalidHeader headerLine) = Char8.unpack
|
||||
$ "The given response header line could not be parsed: "
|
||||
<> headerLine <> "."
|
||||
showHttpExceptionContent (InvalidRequestHeader headerLine) = Char8.unpack
|
||||
$ "The given request header is not compliant: "
|
||||
<> headerLine <> "."
|
||||
showHttpExceptionContent (InternalException interalException) = displayException interalException
|
||||
showHttpExceptionContent (ProxyConnectException _ _ status) = Char8.unpack
|
||||
$ showStatus status
|
||||
<> " status code was returned when trying to connect to the proxy server on the given host and port."
|
||||
showHttpExceptionContent NoResponseDataReceived = "No response data was received from the server at all."
|
||||
showHttpExceptionContent TlsNotSupported = "This HTTP client does not have support for secure connections."
|
||||
showHttpExceptionContent (WrongRequestBodyStreamSize _ _)
|
||||
= "The request body provided did not match the expected size."
|
||||
showHttpExceptionContent (ResponseBodyTooShort _ _) =
|
||||
"The returned response body is too short. Provides the expected size and actual size."
|
||||
showHttpExceptionContent InvalidChunkHeaders = "A chunked response body had invalid headers."
|
||||
showHttpExceptionContent IncompleteHeaders = "An incomplete set of response headers were returned."
|
||||
showHttpExceptionContent (InvalidDestinationHost hostLine) = Char8.unpack
|
||||
$ "The host we tried to connect to is invalid"
|
||||
<> hostLine <> "."
|
||||
showHttpExceptionContent (HttpZlibException zlibException) = displayException zlibException
|
||||
showHttpExceptionContent (InvalidProxyEnvironmentVariable environmentName environmentValue) = Text.unpack
|
||||
$ "Values in the proxy environment variable were invalid: "
|
||||
<> environmentName <> "=\"" <> environmentValue <> "\"."
|
||||
showHttpExceptionContent ConnectionClosed = "Attempted to use a Connection which was already closed"
|
||||
showHttpExceptionContent (InvalidProxySettings _) = "Proxy settings are not valid."
|
||||
handleHttp :: (MonadIO m, MonadCatch m) => Req.HttpException -> m ()
|
||||
handleHttp (Req.VanillaHttpException e)
|
||||
| HttpExceptionRequest _ exceptionContent <- e = printException
|
||||
$ showHttpExceptionContent exceptionContent
|
||||
| InvalidUrlException url reason <- e = printException $ url <> ": " <> reason
|
||||
handleHttp (Req.JsonHttpException e) = printException e
|
||||
handleSome :: (MonadIO m, MonadCatch m) => SomeException -> m ()
|
||||
handleSome = printException . show
|
150
tests/SlackBuilder/InfoSpec.hs
Normal file
150
tests/SlackBuilder/InfoSpec.hs
Normal file
@ -0,0 +1,150 @@
|
||||
{- This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||
v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
obtain one at https://mozilla.org/MPL/2.0/. -}
|
||||
|
||||
module SlackBuilder.InfoSpec
|
||||
( spec
|
||||
) where
|
||||
|
||||
import Crypto.Hash (Digest, MD5, digestFromByteString)
|
||||
import qualified Data.ByteString as ByteString
|
||||
import Data.ByteString.Char8 (ByteString)
|
||||
import Data.Maybe (maybeToList)
|
||||
import qualified Data.Text.Encoding as Text
|
||||
import Data.Void (Void)
|
||||
import SlackBuilder.Info
|
||||
import Test.Hspec (Spec, describe, it, shouldBe)
|
||||
import Test.Hspec.Megaparsec (parseSatisfies, shouldSucceedOn)
|
||||
import Text.Megaparsec (parse)
|
||||
import Text.Megaparsec.Error (ParseErrorBundle)
|
||||
import Text.URI (mkURI)
|
||||
|
||||
parseInfoFile'
|
||||
:: ByteString
|
||||
-> Either (ParseErrorBundle ByteString Void) PackageInfo
|
||||
parseInfoFile' = parse parseInfoFile ""
|
||||
|
||||
infoDownload0 :: ByteString
|
||||
infoDownload0 = "PRGNAM=\"pkgnam\"\n\
|
||||
\VERSION=\"1.2.3\"\n\
|
||||
\HOMEPAGE=\"homepage\"\n\
|
||||
\DOWNLOAD=\"\"\n\
|
||||
\MD5SUM=\"\"\n\
|
||||
\DOWNLOAD_x86_64=\"\"\n\
|
||||
\MD5SUM_x86_64=\"\"\n\
|
||||
\REQUIRES=\"\"\n\
|
||||
\MAINTAINER=\"Z\"\n\
|
||||
\EMAIL=\"test@example.com\"\n"
|
||||
|
||||
infoDownload1 :: ByteString
|
||||
infoDownload1 = "PRGNAM=\"pkgnam\"\n\
|
||||
\VERSION=\"1.2.3\"\n\
|
||||
\HOMEPAGE=\"homepage\"\n\
|
||||
\DOWNLOAD=\"https://dlackware.com/download.tar.gz\"\n\
|
||||
\MD5SUM=\"0102030405060708090a0b0c0d0e0f10\"\n\
|
||||
\DOWNLOAD_x86_64=\"\"\n\
|
||||
\MD5SUM_x86_64=\"\"\n\
|
||||
\REQUIRES=\"\"\n\
|
||||
\MAINTAINER=\"Z\"\n\
|
||||
\EMAIL=\"test@example.com\"\n"
|
||||
|
||||
maybeToDoubleList :: forall a. Maybe a -> [a]
|
||||
maybeToDoubleList xs = [y | x <- maybeToList xs, y <- [x, x]]
|
||||
|
||||
checksumSample :: [Digest MD5]
|
||||
checksumSample = maybeToList $ digestFromByteString (ByteString.pack [1 .. 16])
|
||||
|
||||
spec :: Spec
|
||||
spec = do
|
||||
describe "parseInfoFile" $ do
|
||||
it "returns package on a valid input" $
|
||||
parseInfoFile' `shouldSucceedOn` infoDownload1
|
||||
|
||||
it "returns an array with one element if one download is given" $
|
||||
let condition = (== 1) . length . checksums
|
||||
in parseInfoFile' infoDownload1 `parseSatisfies` condition
|
||||
|
||||
it "translates checksum characters into the binary format" $
|
||||
let expected = ["0102030405060708090a0b0c0d0e0f10"]
|
||||
condition = (== expected) . fmap show . checksums
|
||||
in parseInfoFile' infoDownload1 `parseSatisfies` condition
|
||||
|
||||
it "accepts an empty downloads list" $
|
||||
parseInfoFile' `shouldSucceedOn` infoDownload0
|
||||
|
||||
it "parses a package name with a dot" $
|
||||
let given =
|
||||
"PRGNAM=\"pkgnam.yaml\"\n\
|
||||
\VERSION=\"1.2.3\"\n\
|
||||
\HOMEPAGE=\"homepage\"\n\
|
||||
\DOWNLOAD=\"https://dlackware.com/download.tar.gz\"\n\
|
||||
\MD5SUM=\"0102030405060708090a0b0c0d0e0f10\"\n\
|
||||
\DOWNLOAD_x86_64=\"\"\n\
|
||||
\MD5SUM_x86_64=\"\"\n\
|
||||
\REQUIRES=\"\"\n\
|
||||
\MAINTAINER=\"Z\"\n\
|
||||
\EMAIL=\"test@example.com\"\n"
|
||||
in parseInfoFile' `shouldSucceedOn` given
|
||||
|
||||
it "parses to downloads in a single line" $
|
||||
let given =
|
||||
"PRGNAM=\"pkgnam.yaml\"\n\
|
||||
\VERSION=\"1.2.3\"\n\
|
||||
\HOMEPAGE=\"homepage\"\n\
|
||||
\DOWNLOAD=\"https://dlackware.com/download1.tar.gz https://dlackware.com/download2.tar.gz\"\n\
|
||||
\MD5SUM=\"0102030405060708090a0b0c0d0e0f10 0102030405060708090a0b0c0d0e0f11\"\n\
|
||||
\DOWNLOAD_x86_64=\"\"\n\
|
||||
\MD5SUM_x86_64=\"\"\n\
|
||||
\REQUIRES=\"\"\n\
|
||||
\MAINTAINER=\"Z\"\n\
|
||||
\EMAIL=\"test@example.com\"\n"
|
||||
in parseInfoFile' `shouldSucceedOn` given
|
||||
|
||||
it "parses downloads continuing on the next line" $
|
||||
let given =
|
||||
"PRGNAM=\"pkgnam.yaml\"\n\
|
||||
\VERSION=\"1.2.3\"\n\
|
||||
\HOMEPAGE=\"homepage\"\n\
|
||||
\DOWNLOAD=\"https://dlackware.com/download1.tar.gz \\\n\
|
||||
\ https://dlackware.com/download2.tar.gz\"\n\
|
||||
\MD5SUM=\"0102030405060708090a0b0c0d0e0f10 \\\n\
|
||||
\ 0102030405060708090a0b0c0d0e0f11\"\n\
|
||||
\DOWNLOAD_x86_64=\"\"\n\
|
||||
\MD5SUM_x86_64=\"\"\n\
|
||||
\REQUIRES=\"\"\n\
|
||||
\MAINTAINER=\"Z\"\n\
|
||||
\EMAIL=\"test@example.com\"\n"
|
||||
in parseInfoFile' `shouldSucceedOn` given
|
||||
|
||||
describe "generate" $ do
|
||||
it "generates an .info file without downloads" $
|
||||
let given = PackageInfo "pkgnam" "1.2.3" "homepage" [] [] [] [] [] "Z" "test@example.com"
|
||||
in generate given `shouldBe` Text.decodeUtf8 infoDownload0
|
||||
|
||||
it "splits multiple downloads into multiple lines" $
|
||||
let downloads' = maybeToDoubleList
|
||||
$ mkURI "https://dlackware.com/download.tar.gz"
|
||||
checksums' = maybeToDoubleList
|
||||
$ digestFromByteString (ByteString.pack [1.. 16])
|
||||
given = PackageInfo
|
||||
"pkgnam" "1.2.3" "homepage" downloads' checksums' [] [] [] "Z" "test@example.com"
|
||||
expected = "PRGNAM=\"pkgnam\"\n\
|
||||
\VERSION=\"1.2.3\"\n\
|
||||
\HOMEPAGE=\"homepage\"\n\
|
||||
\DOWNLOAD=\"https://dlackware.com/download.tar.gz \\\n\
|
||||
\ https://dlackware.com/download.tar.gz\"\n\
|
||||
\MD5SUM=\"0102030405060708090a0b0c0d0e0f10 \\\n\
|
||||
\ 0102030405060708090a0b0c0d0e0f10\"\n\
|
||||
\DOWNLOAD_x86_64=\"\"\n\
|
||||
\MD5SUM_x86_64=\"\"\n\
|
||||
\REQUIRES=\"\"\n\
|
||||
\MAINTAINER=\"Z\"\n\
|
||||
\EMAIL=\"test@example.com\"\n"
|
||||
in generate given `shouldBe` expected
|
||||
|
||||
it "prints the checksum as a sequence of hexadecimal numbers" $
|
||||
let downloads' = maybeToList
|
||||
$ mkURI "https://dlackware.com/download.tar.gz"
|
||||
given = PackageInfo
|
||||
"pkgnam" "1.2.3" "homepage" downloads' checksumSample [] [] [] "Z" "test@example.com"
|
||||
in generate given `shouldBe` Text.decodeUtf8 infoDownload1
|
53
tests/SlackBuilder/LatestVersionCheckSpec.hs
Normal file
53
tests/SlackBuilder/LatestVersionCheckSpec.hs
Normal file
@ -0,0 +1,53 @@
|
||||
{- This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||
v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
obtain one at https://mozilla.org/MPL/2.0/. -}
|
||||
|
||||
module SlackBuilder.LatestVersionCheckSpec
|
||||
( spec
|
||||
) where
|
||||
|
||||
import SlackBuilder.LatestVersionCheck
|
||||
import Test.Hspec (Spec, describe, it, shouldBe)
|
||||
|
||||
spec :: Spec
|
||||
spec = do
|
||||
describe "match" $ do
|
||||
it "matches an exact tag prefixed with v" $
|
||||
let expected = Just "2.6.0"
|
||||
actual = match "(v)2.6.0" "v2.6.0"
|
||||
in actual `shouldBe` expected
|
||||
|
||||
it "matches a glob pattern prefixed with v" $
|
||||
let expected = Just "2.6.0"
|
||||
actual = match "(v)*" "v2.6.0"
|
||||
in actual `shouldBe` expected
|
||||
|
||||
it "matches digits" $
|
||||
let expected = Just "2.6.0"
|
||||
actual = match "(v)2.6.\\d" "v2.6.0"
|
||||
in actual `shouldBe` expected
|
||||
|
||||
it "matches digits and dots" $
|
||||
let expected = Just "2.6.0"
|
||||
actual = match "(v)\\." "v2.6.0"
|
||||
in actual `shouldBe` expected
|
||||
|
||||
it "rejects unexpected suffix" $
|
||||
let expected = Nothing
|
||||
actual = match "(v)\\." "v2.6.0-rc1"
|
||||
in actual `shouldBe` expected
|
||||
|
||||
it "rejects remaining umatched characters" $
|
||||
let expected = Nothing
|
||||
actual = match "2.6.0-rc1" "2.6.0"
|
||||
in actual `shouldBe` expected
|
||||
|
||||
it "consumes the last token matching nothing" $
|
||||
let expected = Just "abc"
|
||||
actual = match "abc\\d\\d" "abc"
|
||||
in actual `shouldBe` expected
|
||||
|
||||
it "matches at least one digit" $
|
||||
let expected = Nothing
|
||||
actual = match "1.\\D.3" "1..3"
|
||||
in actual `shouldBe` expected
|
26
tests/SlackBuilder/PackageSpec.hs
Normal file
26
tests/SlackBuilder/PackageSpec.hs
Normal file
@ -0,0 +1,26 @@
|
||||
{- This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||
v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
obtain one at https://mozilla.org/MPL/2.0/. -}
|
||||
|
||||
module SlackBuilder.PackageSpec
|
||||
( spec
|
||||
) where
|
||||
|
||||
import SlackBuilder.Package
|
||||
import Test.Hspec (Spec, describe, it, shouldBe)
|
||||
import Text.URI.QQ (uri)
|
||||
|
||||
spec :: Spec
|
||||
spec = do
|
||||
describe "renderDownloadWithVersion" $ do
|
||||
it "renders text as URL" $
|
||||
let given = DownloadTemplate "https://example.com"
|
||||
actual = renderDownloadWithVersion given "1.2"
|
||||
expected = Just [uri|https://example.com|]
|
||||
in actual `shouldBe` expected
|
||||
|
||||
it "renders the components in order" $
|
||||
let given = DownloadTemplate "https://example.com/{version}/segment"
|
||||
actual = renderDownloadWithVersion given "1.2"
|
||||
expected = Just [uri|https://example.com/1.2/segment|]
|
||||
in actual `shouldBe` expected
|
1
tests/Spec.hs
Normal file
1
tests/Spec.hs
Normal file
@ -0,0 +1 @@
|
||||
{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
|
Reference in New Issue
Block a user