Compare commits
No commits in common. "master" and "v0.1.0" have entirely different histories.
20
.github/workflows/main.yml
vendored
20
.github/workflows/main.yml
vendored
@ -1,20 +0,0 @@
|
|||||||
name: Main
|
|
||||||
|
|
||||||
on: push
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Cache dependencies
|
|
||||||
uses: actions/cache@v1
|
|
||||||
with:
|
|
||||||
path: ~/.stack
|
|
||||||
key: stack-${{ hashFiles('stack.yaml.lock') }}
|
|
||||||
- name: Install GHC
|
|
||||||
run: stack setup
|
|
||||||
- name: Build dependencies
|
|
||||||
run: stack build --only-dependencies
|
|
||||||
- name: Build package
|
|
||||||
run: stack build
|
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,4 +1 @@
|
|||||||
Gemfile.lock
|
|
||||||
_site/
|
|
||||||
|
|
||||||
.stack-work/
|
.stack-work/
|
||||||
|
|||||||
36
CHANGELOG.md
36
CHANGELOG.md
@ -1,36 +0,0 @@
|
|||||||
# 0.4.0 (2020-02-16)
|
|
||||||
|
|
||||||
## Enhancements
|
|
||||||
|
|
||||||
- Use hpack
|
|
||||||
|
|
||||||
# 0.3.0 (2019-02-05)
|
|
||||||
|
|
||||||
## Enhancements
|
|
||||||
|
|
||||||
- Use Stack (executable) to get licenses (ec8412b)
|
|
||||||
- Use `ls dependencies` instead of `list-dependencies` (4f4d41d)
|
|
||||||
|
|
||||||
## Bugs
|
|
||||||
|
|
||||||
- Fix incorrect license if package matches a Hackage package (#23)
|
|
||||||
|
|
||||||
# 0.2.2 (2018-01-16)
|
|
||||||
|
|
||||||
- Allow http-conduit 2.3 (558fe3d)
|
|
||||||
|
|
||||||
# 0.2.1 (2017-07-24)
|
|
||||||
|
|
||||||
- Allow base 4.10 and Cabal 2.0 (7bbb360)
|
|
||||||
|
|
||||||
# 0.2.0 (2016-09-18)
|
|
||||||
|
|
||||||
## Enhancements
|
|
||||||
|
|
||||||
- Allow use in multi-package project (f545a4c)
|
|
||||||
- Handle exceptions (ec640bb)
|
|
||||||
- Replace HTTP with http-conduit (f6735cb)
|
|
||||||
- Add command line arguments (2558a05)
|
|
||||||
- Add a library (835ac70)
|
|
||||||
|
|
||||||
# 0.1.0 (2016-08-13)
|
|
||||||
188
Main.hs
Normal file
188
Main.hs
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||||
|
{-# LANGUAGE NamedFieldPuns #-}
|
||||||
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
|
|
||||||
|
module Main
|
||||||
|
( main
|
||||||
|
)
|
||||||
|
where
|
||||||
|
|
||||||
|
-- base
|
||||||
|
import Control.Monad
|
||||||
|
import Data.List
|
||||||
|
import Data.Monoid ((<>))
|
||||||
|
import qualified System.Exit as Exit
|
||||||
|
import System.IO
|
||||||
|
|
||||||
|
-- Cabal
|
||||||
|
import Distribution.License
|
||||||
|
import Distribution.Package
|
||||||
|
import Distribution.PackageDescription
|
||||||
|
import Distribution.PackageDescription.Parse
|
||||||
|
import Distribution.Simple.Utils
|
||||||
|
import Distribution.Text
|
||||||
|
import Distribution.Verbosity
|
||||||
|
|
||||||
|
-- containers
|
||||||
|
import Data.Map.Strict (Map)
|
||||||
|
import qualified Data.Map.Strict as Map
|
||||||
|
import Data.Set (Set)
|
||||||
|
import qualified Data.Set as Set
|
||||||
|
|
||||||
|
-- directory
|
||||||
|
import System.Directory
|
||||||
|
|
||||||
|
-- HTTP
|
||||||
|
import Network.HTTP
|
||||||
|
( getRequest
|
||||||
|
, getResponseBody
|
||||||
|
, simpleHTTP
|
||||||
|
)
|
||||||
|
|
||||||
|
-- process
|
||||||
|
import System.Process
|
||||||
|
|
||||||
|
|
||||||
|
-- |
|
||||||
|
--
|
||||||
|
--
|
||||||
|
|
||||||
|
newtype License' = License' { _getLicense :: License }
|
||||||
|
deriving (Eq, Read, Show, Text)
|
||||||
|
|
||||||
|
|
||||||
|
-- |
|
||||||
|
--
|
||||||
|
--
|
||||||
|
|
||||||
|
instance Ord License' where
|
||||||
|
compare =
|
||||||
|
comparing display
|
||||||
|
|
||||||
|
|
||||||
|
-- |
|
||||||
|
--
|
||||||
|
--
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
maybePackage <- getPackage
|
||||||
|
|
||||||
|
pid <-
|
||||||
|
case maybePackage of
|
||||||
|
Nothing ->
|
||||||
|
Exit.die "Error: No Cabal file found."
|
||||||
|
|
||||||
|
Just PackageDescription{..} -> do
|
||||||
|
putStrLn $
|
||||||
|
"Package: "
|
||||||
|
<> display package
|
||||||
|
<> " ("
|
||||||
|
<> "License: "
|
||||||
|
<> display license
|
||||||
|
<> ")"
|
||||||
|
return package
|
||||||
|
|
||||||
|
maybeDependencies <- getDependencies
|
||||||
|
|
||||||
|
case maybeDependencies of
|
||||||
|
Nothing ->
|
||||||
|
Exit.die "Error: ..."
|
||||||
|
|
||||||
|
Just dependencies -> do
|
||||||
|
dependenciesByLicense <-
|
||||||
|
fmap (Set.map display) <$> orderPackagesByLicense pid dependencies
|
||||||
|
|
||||||
|
forM_ (Map.keys dependenciesByLicense) $
|
||||||
|
\license ->
|
||||||
|
let
|
||||||
|
n = dependenciesByLicense Map.! license
|
||||||
|
in do
|
||||||
|
putStrLn "-----"
|
||||||
|
putStrLn $
|
||||||
|
show (Set.size n)
|
||||||
|
<> (if Set.size n == 1 then " package " else " packages ")
|
||||||
|
<> "licensed under "
|
||||||
|
<> display license
|
||||||
|
<> ": "
|
||||||
|
<> intercalate ", " (Set.toList n)
|
||||||
|
|
||||||
|
|
||||||
|
-- |
|
||||||
|
--
|
||||||
|
--
|
||||||
|
|
||||||
|
getPackage :: IO (Maybe PackageDescription)
|
||||||
|
getPackage = do
|
||||||
|
currentDirectory <- getCurrentDirectory
|
||||||
|
fmap getPackageDescription <$> findPackageDesc currentDirectory
|
||||||
|
>>= either (const (return Nothing)) (fmap Just)
|
||||||
|
|
||||||
|
|
||||||
|
-- |
|
||||||
|
--
|
||||||
|
--
|
||||||
|
|
||||||
|
getPackageDescription :: FilePath -> IO PackageDescription
|
||||||
|
getPackageDescription =
|
||||||
|
fmap packageDescription . readPackageDescription silent
|
||||||
|
|
||||||
|
|
||||||
|
-- |
|
||||||
|
--
|
||||||
|
--
|
||||||
|
|
||||||
|
getDependencies :: IO (Maybe (Set PackageIdentifier))
|
||||||
|
getDependencies =
|
||||||
|
fmap Set.fromList . sequence . fmap simpleParse . lines
|
||||||
|
<$> readProcess "stack" ["list-dependencies", "--separator", "-"] ""
|
||||||
|
|
||||||
|
|
||||||
|
-- |
|
||||||
|
--
|
||||||
|
--
|
||||||
|
|
||||||
|
getPackageLicense :: PackageIdentifier -> IO License'
|
||||||
|
getPackageLicense p@PackageIdentifier{..} = do
|
||||||
|
let
|
||||||
|
url =
|
||||||
|
"http://hackage.haskell.org/package/"
|
||||||
|
<> display p
|
||||||
|
<> "/"
|
||||||
|
<> unPackageName pkgName
|
||||||
|
<> ".cabal"
|
||||||
|
pd <- simpleHTTP (getRequest url) >>= getResponseBody
|
||||||
|
(file, handle) <- openTempFile "/tmp" "licensor"
|
||||||
|
hClose handle
|
||||||
|
writeFile file pd
|
||||||
|
PackageDescription{license} <- getPackageDescription file
|
||||||
|
hClose handle
|
||||||
|
removeFile file
|
||||||
|
return (License' license)
|
||||||
|
|
||||||
|
|
||||||
|
-- |
|
||||||
|
--
|
||||||
|
--
|
||||||
|
|
||||||
|
orderPackagesByLicense
|
||||||
|
:: PackageIdentifier
|
||||||
|
-> Set PackageIdentifier
|
||||||
|
-> IO (Map License' (Set PackageIdentifier))
|
||||||
|
orderPackagesByLicense p =
|
||||||
|
let
|
||||||
|
insertPackage package orderedPackages' = do
|
||||||
|
license <- getPackageLicense package
|
||||||
|
orderedPackages <- orderedPackages'
|
||||||
|
return $
|
||||||
|
if p == package
|
||||||
|
then
|
||||||
|
orderedPackages
|
||||||
|
else
|
||||||
|
Map.insertWith
|
||||||
|
Set.union
|
||||||
|
license
|
||||||
|
(Set.singleton package)
|
||||||
|
orderedPackages
|
||||||
|
in
|
||||||
|
foldr insertPackage (pure mempty)
|
||||||
172
README.md
172
README.md
@ -1,171 +1 @@
|
|||||||
# The not so great automatic Haskell licensor
|
# licensor
|
||||||
|
|
||||||
[![][2]](https://www.stackage.org/lts/package/licensor)
|
|
||||||
[![][3]](https://www.stackage.org/nightly/package/licensor)
|
|
||||||
|
|
||||||
[2]: https://www.stackage.org/package/licensor/badge/lts
|
|
||||||
[3]: https://www.stackage.org/package/licensor/badge/nightly
|
|
||||||
|
|
||||||
Licensor is a program that generates a report of the dependencies and
|
|
||||||
transitive dependencies of a Haskell project and their licenses.
|
|
||||||
|
|
||||||
## Description
|
|
||||||
|
|
||||||
Choosing a license for a software project or determining whether a
|
|
||||||
particular dependency can be added to a project can be projects
|
|
||||||
themselves. Unless starting from scratch, programmers should consider
|
|
||||||
the licenses of the dependencies and transitive dependencies of their
|
|
||||||
projects to make informed decisions and avoid license compatibility
|
|
||||||
issues.
|
|
||||||
|
|
||||||
Of course, this is just a starting point. "Beyond (...) general
|
|
||||||
observations, it is difficult, if not impossible, to provide precise
|
|
||||||
guidance about what licenses may or may not be compatible with each
|
|
||||||
other. (...) Programmers who are considering combining code governed
|
|
||||||
by two or more different licenses should proceed cautiously" (Andrew
|
|
||||||
M. St. Laurent).
|
|
||||||
|
|
||||||
## Disclaimer
|
|
||||||
|
|
||||||
Licensor is not a lawyer and does not provide legal advice.
|
|
||||||
|
|
||||||
For more information about licenses and license compatibility issues,
|
|
||||||
read the text of the licenses or consult with a lawyer before making
|
|
||||||
any decision.
|
|
||||||
|
|
||||||
## Related programs
|
|
||||||
|
|
||||||
Licensor is not the only license compatibility helper for Haskell:
|
|
||||||
|
|
||||||
- Licensor uses a Cabal library and Stack program approach for
|
|
||||||
detecting licenses and listing dependencies, respectively. For a
|
|
||||||
Cabal library and program approach, consider using
|
|
||||||
the [cabal-dependency-licenses][rp-01] program.
|
|
||||||
|
|
||||||
[rp-01]: https://hackage.haskell.org/package/cabal-dependency-licenses
|
|
||||||
|
|
||||||
## Installation and usage
|
|
||||||
|
|
||||||
To install Licensor, use Cabal:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ cabal update && cabal install licensor
|
|
||||||
```
|
|
||||||
|
|
||||||
Then, run the `licensor` executable inside a Haskell project:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ licensor
|
|
||||||
```
|
|
||||||
|
|
||||||
To see the license report for Licensor, clone the repository:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ git clone https://github.com/jpvillaisaza/licensor
|
|
||||||
```
|
|
||||||
|
|
||||||
And run `licensor` inside the project:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ cd licensor/ && licensor
|
|
||||||
```
|
|
||||||
|
|
||||||
Or build and run `licensor` inside the project:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ cd licensor/ && stack build --exec licensor
|
|
||||||
```
|
|
||||||
|
|
||||||
For more information, run `licensor --help`:
|
|
||||||
|
|
||||||
```
|
|
||||||
licensor 0.4.0
|
|
||||||
|
|
||||||
licensor [OPTIONS]
|
|
||||||
|
|
||||||
Common flags:
|
|
||||||
-? --help Display help message
|
|
||||||
-V --version Print version information
|
|
||||||
--numeric-version Print just the version number
|
|
||||||
-v --verbose Loud verbosity
|
|
||||||
-q --quiet Quiet verbosity
|
|
||||||
```
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
### Dependencies
|
|
||||||
|
|
||||||
Licensor uses the Stack program to list dependencies for a Haskell
|
|
||||||
project. A future enhancement could be to use the Stack library.
|
|
||||||
|
|
||||||
### Licenses and license detection
|
|
||||||
|
|
||||||
Licensor uses the Cabal library to detect the license of a Haskell
|
|
||||||
project and its dependencies (including transitive dependencies). To
|
|
||||||
do so, it uses the license field in the package description. A future
|
|
||||||
enhancement could be to use both the license and licence file fields
|
|
||||||
in the package description.
|
|
||||||
|
|
||||||
Cabal provides an enumeration of common open source and free software
|
|
||||||
licenses. These are the licenses that appear in the reports generated
|
|
||||||
by Licensor:
|
|
||||||
|
|
||||||
License | Description
|
|
||||||
------------------------- | -------------------------
|
|
||||||
GPL | GNU General Public License
|
|
||||||
AGPL | GNU Affero General Public License
|
|
||||||
LGPL | GNU Lesser General Public License
|
|
||||||
BSD2 | BSD 2-Clause License
|
|
||||||
BSD3 | BSD 3-Clause License
|
|
||||||
BSD4 | BSD 4-Clause License
|
|
||||||
MIT | MIT License
|
|
||||||
ISC | ISC License
|
|
||||||
MPL | Mozilla Public License
|
|
||||||
Apache | Apache License
|
|
||||||
PublicDomain | Public domain
|
|
||||||
AllRightsReserved | All rights reserved
|
|
||||||
UnspecifiedLicense | Unspecified license (All rights reserved)
|
|
||||||
OtherLicense | Other license
|
|
||||||
UnknownLicense | Unknown license
|
|
||||||
|
|
||||||
## Contribution guidelines
|
|
||||||
|
|
||||||
Feel free to create issues for reporting bugs and suggesting
|
|
||||||
enhancements, or to fork the repository and open a pull request.
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
Licensor is licensed under the MIT License.
|
|
||||||
See [LICENSE.md](LICENSE.md).
|
|
||||||
|
|
||||||
### License report
|
|
||||||
|
|
||||||
Licensor (0.4.0) depends on the following libraries:
|
|
||||||
|
|
||||||
Library | License
|
|
||||||
------------------------- | -------------------------
|
|
||||||
base | BSD3
|
|
||||||
Cabal | BSD3
|
|
||||||
cmdargs | BSD3
|
|
||||||
containers | BSD3
|
|
||||||
directory | BSD3
|
|
||||||
process | BSD3
|
|
||||||
|
|
||||||
And the following licenses (including transitive dependencies):
|
|
||||||
|
|
||||||
License | Number of libraries
|
|
||||||
------------------------- | -------------------------
|
|
||||||
BSD3 | 20
|
|
||||||
|
|
||||||
(Tested with Licensor 0.4.0, Stack 2.1.3, and LTS Haskell 11.11.)
|
|
||||||
|
|
||||||
## Additional resources
|
|
||||||
|
|
||||||
- [Choose a License](https://choosealicense.com/)
|
|
||||||
- [The Legal Side of Open Source](https://opensource.guide/legal/)
|
|
||||||
- [License compatibility][ar-01]
|
|
||||||
- [Understanding open source and free software licensing][ar-02]
|
|
||||||
(Andrew M. St. Laurent)
|
|
||||||
|
|
||||||
[ar-01]: https://en.wikipedia.org/wiki/License_compatibility
|
|
||||||
[ar-02]: http://www.oreilly.com/openbook/osfreesoft/book/
|
|
||||||
|
|||||||
11
Setup.hs
Normal file
11
Setup.hs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
module Main
|
||||||
|
( main
|
||||||
|
)
|
||||||
|
where
|
||||||
|
|
||||||
|
import Distribution.Simple (defaultMain)
|
||||||
|
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main =
|
||||||
|
defaultMain
|
||||||
18
_config.yml
18
_config.yml
@ -1,18 +0,0 @@
|
|||||||
exclude:
|
|
||||||
- app/
|
|
||||||
- CHANGELOG.md
|
|
||||||
- Gemfile
|
|
||||||
- Gemfile.lock
|
|
||||||
- LICENSE.md
|
|
||||||
- licensor.cabal
|
|
||||||
- package.yaml
|
|
||||||
- src/
|
|
||||||
- package.yaml
|
|
||||||
- stack.yaml
|
|
||||||
- stack.yaml.lock
|
|
||||||
|
|
||||||
plugins:
|
|
||||||
- jekyll-readme-index
|
|
||||||
|
|
||||||
readme_index:
|
|
||||||
remove_originals: true
|
|
||||||
131
app/Main.hs
131
app/Main.hs
@ -1,131 +0,0 @@
|
|||||||
{-# LANGUAGE DeriveDataTypeable #-}
|
|
||||||
{-# LANGUAGE NamedFieldPuns #-}
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
-- |
|
|
||||||
-- Module: Main
|
|
||||||
-- Description:
|
|
||||||
--
|
|
||||||
--
|
|
||||||
--
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
|
|
||||||
module Main
|
|
||||||
( main
|
|
||||||
)
|
|
||||||
where
|
|
||||||
|
|
||||||
-- licensor
|
|
||||||
import Licensor
|
|
||||||
|
|
||||||
-- base
|
|
||||||
import Control.Monad
|
|
||||||
import Data.List
|
|
||||||
import Data.Monoid ((<>))
|
|
||||||
import qualified Data.Version as Version
|
|
||||||
import System.Environment
|
|
||||||
import qualified System.Exit as Exit
|
|
||||||
|
|
||||||
-- Cabal
|
|
||||||
import Distribution.PackageDescription
|
|
||||||
import Distribution.Text
|
|
||||||
|
|
||||||
-- cmdargs
|
|
||||||
import System.Console.CmdArgs
|
|
||||||
|
|
||||||
-- containers
|
|
||||||
import qualified Data.Map.Strict as Map
|
|
||||||
import qualified Data.Set as Set
|
|
||||||
|
|
||||||
-- directory
|
|
||||||
import System.Directory (doesFileExist)
|
|
||||||
|
|
||||||
|
|
||||||
-- |
|
|
||||||
--
|
|
||||||
--
|
|
||||||
|
|
||||||
data LiArgs =
|
|
||||||
LiArgs
|
|
||||||
{
|
|
||||||
}
|
|
||||||
deriving (Data)
|
|
||||||
|
|
||||||
|
|
||||||
-- |
|
|
||||||
--
|
|
||||||
--
|
|
||||||
|
|
||||||
liArgs :: String -> Mode (CmdArgs LiArgs)
|
|
||||||
liArgs s =
|
|
||||||
cmdArgsMode $
|
|
||||||
LiArgs
|
|
||||||
{
|
|
||||||
}
|
|
||||||
&= program s
|
|
||||||
&= summary (unwords ["licensor", Version.showVersion version])
|
|
||||||
&= verbosity
|
|
||||||
|
|
||||||
|
|
||||||
-- |
|
|
||||||
--
|
|
||||||
--
|
|
||||||
|
|
||||||
main :: IO ()
|
|
||||||
main = do
|
|
||||||
LiArgs <- cmdArgsRun . liArgs =<< getProgName
|
|
||||||
|
|
||||||
quiet <- fmap not isNormal
|
|
||||||
|
|
||||||
maybePackage <- getPackage
|
|
||||||
|
|
||||||
pid <-
|
|
||||||
case maybePackage of
|
|
||||||
Nothing -> do
|
|
||||||
stack <- doesFileExist "stack.yaml"
|
|
||||||
if stack
|
|
||||||
then do
|
|
||||||
putStrLn "Found stack.yaml..."
|
|
||||||
pure Nothing
|
|
||||||
else
|
|
||||||
Exit.die "Error: No Cabal file found."
|
|
||||||
|
|
||||||
Just PackageDescription { license, package } -> do
|
|
||||||
putStrLn $
|
|
||||||
"Package: "
|
|
||||||
<> display package
|
|
||||||
<> " ("
|
|
||||||
<> "License: "
|
|
||||||
<> display license
|
|
||||||
<> ")"
|
|
||||||
pure (Just package)
|
|
||||||
|
|
||||||
maybeDependencies <- getDependencies
|
|
||||||
maybeLicenses <- getLicenses
|
|
||||||
|
|
||||||
case (maybeDependencies, maybeLicenses) of
|
|
||||||
(Just dependencies, Just licenses) -> do
|
|
||||||
(dependenciesByLicense', failed) <-
|
|
||||||
orderPackagesByLicense quiet pid licenses dependencies
|
|
||||||
|
|
||||||
let dependenciesByLicense = fmap (Set.map display) dependenciesByLicense'
|
|
||||||
|
|
||||||
forM_ (Map.keys dependenciesByLicense) $
|
|
||||||
\license ->
|
|
||||||
let
|
|
||||||
n = dependenciesByLicense Map.! license
|
|
||||||
in do
|
|
||||||
putStrLn "-----"
|
|
||||||
putStrLn $
|
|
||||||
show (Set.size n)
|
|
||||||
<> (if Set.size n == 1 then " package " else " packages ")
|
|
||||||
<> "licensed under "
|
|
||||||
<> display license
|
|
||||||
<> ": "
|
|
||||||
<> intercalate ", " (Set.toList n)
|
|
||||||
|
|
||||||
unless (null failed) $ do
|
|
||||||
putStr "Failed: "
|
|
||||||
print failed
|
|
||||||
_ ->
|
|
||||||
Exit.die "Error: ..."
|
|
||||||
@ -1,61 +1,34 @@
|
|||||||
cabal-version: 1.12
|
name: licensor
|
||||||
|
version: 0.1.0
|
||||||
|
synopsis: A license compatibility helper
|
||||||
|
description: A license compatibility helper.
|
||||||
|
homepage: https://github.com/jpvillaisaza/licensor
|
||||||
|
bug-reports: https://github.com/jpvillaisaza/licensor/issues
|
||||||
|
license: MIT
|
||||||
|
license-file: LICENSE.md
|
||||||
|
author: Juan Pedro Villa Isaza <jpvillaisaza@gmail.com>
|
||||||
|
maintainer: Juan Pedro Villa Isaza <jpvillaisaza@gmail.com>
|
||||||
|
copyright: 2016 Juan Pedro Villa Isaza
|
||||||
|
category: Distribution
|
||||||
|
extra-source-files: README.md
|
||||||
|
build-type: Simple
|
||||||
|
cabal-version: >= 1.10
|
||||||
|
|
||||||
-- This file has been generated from package.yaml by hpack version 0.31.2.
|
executable licensor
|
||||||
--
|
main-is:
|
||||||
-- see: https://github.com/sol/hpack
|
Main.hs
|
||||||
--
|
build-depends:
|
||||||
-- hash: b5e0234d196e96476a6a70c11798ae1dd4fd24ca9ce1c11ea74d6b3422604fc8
|
base >= 4.8 && < 5.0
|
||||||
|
, Cabal >= 1.22 && < 1.25
|
||||||
name: licensor
|
, containers
|
||||||
version: 0.4.0
|
, directory
|
||||||
synopsis: A license compatibility helper
|
, HTTP >= 4000.3 && < 4000.4
|
||||||
description: A license compatibility helper.
|
, process
|
||||||
category: Distribution
|
default-language:
|
||||||
stability: Experimental
|
Haskell2010
|
||||||
homepage: https://jpvillaisaza.co/licensor
|
ghc-options:
|
||||||
bug-reports: https://github.com/jpvillaisaza/licensor/issues
|
-Wall -threaded -rtsopts -with-rtsopts=-N
|
||||||
author: Juan Pedro Villa Isaza <jpvillaisaza@gmail.com>
|
|
||||||
maintainer: Juan Pedro Villa Isaza <jpvillaisaza@gmail.com>
|
|
||||||
copyright: 2016 Juan Pedro Villa Isaza
|
|
||||||
license: MIT
|
|
||||||
license-file: LICENSE.md
|
|
||||||
build-type: Simple
|
|
||||||
extra-source-files:
|
|
||||||
CHANGELOG.md
|
|
||||||
README.md
|
|
||||||
|
|
||||||
source-repository head
|
source-repository head
|
||||||
type: git
|
type: git
|
||||||
location: https://github.com/jpvillaisaza/licensor
|
location: https://github.com/jpvillaisaza/licensor
|
||||||
|
|
||||||
library
|
|
||||||
exposed-modules:
|
|
||||||
Licensor
|
|
||||||
other-modules:
|
|
||||||
Paths_licensor
|
|
||||||
hs-source-dirs:
|
|
||||||
src
|
|
||||||
ghc-options: -Wall
|
|
||||||
build-depends:
|
|
||||||
Cabal >=1.22 && <2.1
|
|
||||||
, base >=4.8 && <4.11
|
|
||||||
, containers
|
|
||||||
, directory
|
|
||||||
, process
|
|
||||||
default-language: Haskell2010
|
|
||||||
|
|
||||||
executable licensor
|
|
||||||
main-is: Main.hs
|
|
||||||
other-modules:
|
|
||||||
Paths_licensor
|
|
||||||
hs-source-dirs:
|
|
||||||
app
|
|
||||||
ghc-options: -Wall -threaded -rtsopts -with-rtsopts=-N
|
|
||||||
build-depends:
|
|
||||||
Cabal >=1.22 && <2.1
|
|
||||||
, base >=4.8 && <4.11
|
|
||||||
, cmdargs >=0.10 && <0.11
|
|
||||||
, containers
|
|
||||||
, directory
|
|
||||||
, licensor
|
|
||||||
default-language: Haskell2010
|
|
||||||
|
|||||||
49
package.yaml
49
package.yaml
@ -1,49 +0,0 @@
|
|||||||
name: licensor
|
|
||||||
version: 0.4.0
|
|
||||||
|
|
||||||
synopsis: A license compatibility helper
|
|
||||||
description: A license compatibility helper.
|
|
||||||
|
|
||||||
category: Distribution
|
|
||||||
|
|
||||||
stability: Experimental
|
|
||||||
github: jpvillaisaza/licensor
|
|
||||||
homepage: https://jpvillaisaza.co/licensor
|
|
||||||
|
|
||||||
author: Juan Pedro Villa Isaza <jpvillaisaza@gmail.com>
|
|
||||||
maintainer: Juan Pedro Villa Isaza <jpvillaisaza@gmail.com>
|
|
||||||
copyright: 2016 Juan Pedro Villa Isaza
|
|
||||||
|
|
||||||
license-file: LICENSE.md
|
|
||||||
|
|
||||||
extra-source-files:
|
|
||||||
- CHANGELOG.md
|
|
||||||
- README.md
|
|
||||||
|
|
||||||
dependencies:
|
|
||||||
- Cabal >= 1.22 && < 2.1
|
|
||||||
- base >= 4.8 && < 4.11
|
|
||||||
- containers
|
|
||||||
- directory
|
|
||||||
|
|
||||||
ghc-options:
|
|
||||||
- -Wall
|
|
||||||
|
|
||||||
library:
|
|
||||||
source-dirs:
|
|
||||||
src
|
|
||||||
dependencies:
|
|
||||||
- process
|
|
||||||
|
|
||||||
executable:
|
|
||||||
source-dirs:
|
|
||||||
app
|
|
||||||
main:
|
|
||||||
Main.hs
|
|
||||||
dependencies:
|
|
||||||
- cmdargs >= 0.10 && < 0.11
|
|
||||||
- licensor
|
|
||||||
ghc-options:
|
|
||||||
- -threaded
|
|
||||||
- -rtsopts
|
|
||||||
- -with-rtsopts=-N
|
|
||||||
207
src/Licensor.hs
207
src/Licensor.hs
@ -1,207 +0,0 @@
|
|||||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
|
||||||
{-# LANGUAGE ScopedTypeVariables #-}
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
-- |
|
|
||||||
-- Module: Licensor
|
|
||||||
-- Description:
|
|
||||||
--
|
|
||||||
--
|
|
||||||
--
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
|
|
||||||
module Licensor
|
|
||||||
( LiLicense(..)
|
|
||||||
, LiPackage(..)
|
|
||||||
, getDependencies
|
|
||||||
, getLicenses
|
|
||||||
, getPackage
|
|
||||||
, orderPackagesByLicense
|
|
||||||
, version
|
|
||||||
)
|
|
||||||
where
|
|
||||||
|
|
||||||
-- base
|
|
||||||
import qualified Control.Exception as Exception
|
|
||||||
import Control.Monad (unless)
|
|
||||||
import Data.Version (Version)
|
|
||||||
|
|
||||||
-- Cabal
|
|
||||||
import Distribution.License (License)
|
|
||||||
import Distribution.Package (PackageIdentifier(..), PackageName)
|
|
||||||
import Distribution.PackageDescription (PackageDescription, packageDescription)
|
|
||||||
import Distribution.PackageDescription.Parse (readGenericPackageDescription)
|
|
||||||
import Distribution.Simple.Utils (comparing, findPackageDesc)
|
|
||||||
import Distribution.Text (Text, display, simpleParse)
|
|
||||||
import Distribution.Verbosity (silent)
|
|
||||||
|
|
||||||
-- containers
|
|
||||||
import Data.Map.Strict (Map)
|
|
||||||
import qualified Data.Map.Strict as Map
|
|
||||||
import Data.Set (Set)
|
|
||||||
import qualified Data.Set as Set
|
|
||||||
|
|
||||||
-- directory
|
|
||||||
import System.Directory (getCurrentDirectory)
|
|
||||||
|
|
||||||
-- licensor
|
|
||||||
import qualified Paths_licensor
|
|
||||||
|
|
||||||
-- process
|
|
||||||
import System.Process (readProcess)
|
|
||||||
|
|
||||||
|
|
||||||
-- |
|
|
||||||
--
|
|
||||||
--
|
|
||||||
|
|
||||||
newtype LiLicense = LiLicense { getLicense :: License }
|
|
||||||
deriving (Eq, Read, Show, Text)
|
|
||||||
|
|
||||||
|
|
||||||
-- |
|
|
||||||
--
|
|
||||||
--
|
|
||||||
|
|
||||||
instance Ord LiLicense where
|
|
||||||
compare =
|
|
||||||
comparing display
|
|
||||||
|
|
||||||
|
|
||||||
-- |
|
|
||||||
--
|
|
||||||
--
|
|
||||||
|
|
||||||
data LiPackage =
|
|
||||||
LiPackage
|
|
||||||
{ liPackageId :: PackageIdentifier
|
|
||||||
, liPackageDependencies :: Set LiPackage
|
|
||||||
, liPackageLicense :: License
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
-- |
|
|
||||||
--
|
|
||||||
--
|
|
||||||
|
|
||||||
getPackage :: IO (Maybe PackageDescription)
|
|
||||||
getPackage = do
|
|
||||||
currentDirectory <- getCurrentDirectory
|
|
||||||
fmap getPackageDescription <$> findPackageDesc currentDirectory
|
|
||||||
>>= either (const (pure Nothing)) (fmap Just)
|
|
||||||
|
|
||||||
|
|
||||||
-- |
|
|
||||||
--
|
|
||||||
--
|
|
||||||
|
|
||||||
getPackageDescription :: FilePath -> IO PackageDescription
|
|
||||||
getPackageDescription =
|
|
||||||
fmap packageDescription . readGenericPackageDescription silent
|
|
||||||
|
|
||||||
|
|
||||||
-- |
|
|
||||||
--
|
|
||||||
--
|
|
||||||
|
|
||||||
getDependencies :: IO (Maybe (Set PackageIdentifier))
|
|
||||||
getDependencies = do
|
|
||||||
eitherDeps <-
|
|
||||||
Exception.try $ readProcess "stack" ["ls", "dependencies", "--separator", "-"] ""
|
|
||||||
|
|
||||||
case eitherDeps of
|
|
||||||
Left (_ :: IOError) ->
|
|
||||||
pure Nothing
|
|
||||||
|
|
||||||
Right deps ->
|
|
||||||
pure $ Set.fromList <$> traverse simpleParse (lines deps)
|
|
||||||
|
|
||||||
|
|
||||||
getLicenses :: IO (Maybe [(PackageName, License)])
|
|
||||||
getLicenses = do
|
|
||||||
eitherDeps <-
|
|
||||||
Exception.try $ readProcess "stack" ["ls", "dependencies", "--license"] ""
|
|
||||||
|
|
||||||
case eitherDeps of
|
|
||||||
Left (_ :: IOError) ->
|
|
||||||
pure Nothing
|
|
||||||
|
|
||||||
Right deps ->
|
|
||||||
pure $ traverse toNameLicense (lines deps)
|
|
||||||
where
|
|
||||||
toNameLicense dep =
|
|
||||||
case words dep of
|
|
||||||
[name, license] ->
|
|
||||||
(,) <$> simpleParse name <*> simpleParse license
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
Nothing
|
|
||||||
|
|
||||||
|
|
||||||
-- |
|
|
||||||
--
|
|
||||||
--
|
|
||||||
|
|
||||||
getPackageLicense
|
|
||||||
:: Bool
|
|
||||||
-> PackageIdentifier
|
|
||||||
-> [(PackageName, License)]
|
|
||||||
-> IO (Maybe LiLicense)
|
|
||||||
getPackageLicense quiet packageIdentifier licenses = do
|
|
||||||
unless quiet (putStr $ display packageIdentifier ++ "...")
|
|
||||||
case lookup (pkgName packageIdentifier) licenses of
|
|
||||||
Just license -> do
|
|
||||||
unless quiet (putStrLn $ display license)
|
|
||||||
pure $ Just (LiLicense license)
|
|
||||||
Nothing ->
|
|
||||||
pure Nothing
|
|
||||||
|
|
||||||
|
|
||||||
-- |
|
|
||||||
--
|
|
||||||
--
|
|
||||||
|
|
||||||
orderPackagesByLicense
|
|
||||||
:: Bool
|
|
||||||
-> Maybe PackageIdentifier
|
|
||||||
-> [(PackageName, License)]
|
|
||||||
-> Set PackageIdentifier
|
|
||||||
-> IO (Map LiLicense (Set PackageIdentifier), Set PackageIdentifier)
|
|
||||||
orderPackagesByLicense quiet maybeP licenses =
|
|
||||||
let
|
|
||||||
cond =
|
|
||||||
maybe (const False) (==) maybeP
|
|
||||||
|
|
||||||
insertPackage package orderedPackages' = do
|
|
||||||
maybeLicense <- getPackageLicense quiet package licenses
|
|
||||||
|
|
||||||
(orderedPackages, failed) <- orderedPackages'
|
|
||||||
pure $
|
|
||||||
if cond package
|
|
||||||
then
|
|
||||||
(orderedPackages, failed)
|
|
||||||
else
|
|
||||||
case maybeLicense of
|
|
||||||
Nothing ->
|
|
||||||
( orderedPackages, Set.insert package failed
|
|
||||||
)
|
|
||||||
|
|
||||||
Just license ->
|
|
||||||
( Map.insertWith
|
|
||||||
Set.union
|
|
||||||
license
|
|
||||||
(Set.singleton package)
|
|
||||||
orderedPackages
|
|
||||||
, failed
|
|
||||||
)
|
|
||||||
in
|
|
||||||
foldr insertPackage (pure (mempty, mempty))
|
|
||||||
|
|
||||||
|
|
||||||
-- |
|
|
||||||
--
|
|
||||||
--
|
|
||||||
|
|
||||||
version :: Version
|
|
||||||
version =
|
|
||||||
Paths_licensor.version
|
|
||||||
@ -1 +1 @@
|
|||||||
resolver: lts-11.11
|
resolver: lts-6.11
|
||||||
|
|||||||
@ -1,12 +0,0 @@
|
|||||||
# This file was autogenerated by Stack.
|
|
||||||
# You should not edit this file by hand.
|
|
||||||
# For more information, please see the documentation at:
|
|
||||||
# https://docs.haskellstack.org/en/stable/lock_files
|
|
||||||
|
|
||||||
packages: []
|
|
||||||
snapshots:
|
|
||||||
- completed:
|
|
||||||
size: 507599
|
|
||||||
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/11/11.yaml
|
|
||||||
sha256: 5ec0a1ff4dadde524eb529784556bcc32014422fd1e1ed91231c59f001e92ca9
|
|
||||||
original: lts-11.11
|
|
||||||
Loading…
Reference in New Issue
Block a user