Git Product home page Git Product logo

shards's Introduction

Shards

CI

Dependency manager for the Crystal language.

Usage

Crystal applications and libraries are expected to have a shard.yml file at their root looking like this:

name: shards
version: 0.1.0

dependencies:
  openssl:
    github: datanoise/openssl.cr
    branch: master

development_dependencies:
  minitest:
    git: https://github.com/ysbaddaden/minitest.cr.git
    version: ~> 0.3.1

license: MIT

When libraries are installed from Git repositories, the repository is expected to have version tags following a semver-like format, prefixed with a v. Examples: v1.2.3, v2.0.0-rc1 or v2017.04.1.

Please see the SPEC for more details about the shard.yml format.

Install

Shards is usually distributed with Crystal itself (e.g. Homebrew and Debian packages). Alternatively, a shards package may be available for your system.

You can download a source tarball from the same page (or clone the repository) then run make release=1and copy bin/shards into your PATH. For example /usr/local/bin.

You are now ready to create a shard.yml for your projects (see details in SPEC). You can type shards init to have an example shard.yml file created for your project.

Run shards install to install your dependencies, which will lock your dependencies into a shard.lock file. You should check both shard.yml and shard.lock into version control, so further shards install will always install locked versions, achieving reproducible installations across computers.

Run shards --help to list other commands with their options.

Happy Hacking!

Developers

Requirements

These requirements are only necessary for compiling Shards.

  • Crystal

    Please refer to https://crystal-lang.org/install/ for instructions for your operating system.

  • molinillo

    The shard molinillo needs to be in the Crystal path. It is available at https://github.com/crystal-lang/crystal-molinillo You can install it either with a pre-existing shards binary (running shards install) or just check out the repository at lib/crystal-molinillo (make lib).

  • libyaml

    On Debian/Ubuntu Linux you may install the libyaml-dev package.

    On Mac OS X you may install it using homebrew with brew install libyaml then make sure to have /usr/local/lib in your LIBRARY_PATH environment variable (eg: export LIBRARY_PATH="/usr/local/lib:$LIBRARY_PATH"). Please adjust the path per your Homebrew installation.

  • asciidoctor

    Needed for building manpages.

Getting started

It is strongly recommended to use make for building shards and developing it. The Makefile contains recipes for compiling and testing. Building with make also ensures the source dependency molinillo is installed. You don't need to take care of this yourself.

Run make bin/shards to build the binary.

  • release=1 for a release build (applies optimizations)
  • static=1 for static linking (only works with musl-libc)
  • debug=1 for full symbolic debug info

Run make install to install the binary. Target path can be adjusted with PREFIX (default: PREFIX=/usr/bin).

Run make test to run the test suites:

  • make test_unit runs unit tests (./spec/unit)
  • make test_integration runs integration tests (./spec/integration) on bin/shards

Run make docs to build the manpages.

License

Licensed under the Apache License, Version 2.0. See LICENSE for details.

shards's People

Contributors

asterite avatar bcardiff avatar beta-ziliani avatar elebow avatar f-fr avatar hertzdevil avatar jessedoyle avatar jhass avatar kalafut avatar kimburgess avatar kojix2 avatar luislavena avatar lzap avatar mistressremilia avatar mjoerussell avatar nobodywasishere avatar oprypin avatar rx14 avatar samueleaton avatar sija avatar soveran avatar splattael avatar sstarr avatar stakach avatar straight-shoota avatar szabgab avatar waj avatar willamin avatar ysbaddaden avatar zatherz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

shards's Issues

Initial Documentation

Shards is missing some documentation for:

  • its specs: shard.yml see SPEC;
  • project expectations: Git tags, versions (semver), ...;
  • CLI usages (commands, options, ...), see 8aca7de
  • manual installation instructions, see #34

refs #10

New command: validate

Since the shard.yml has a SPEC it would be nice to have a validator that ensures that a given shard.yml file is valid.

Include Git commit information on --version output

Hello,

Current Shards output provides the date of the build, but no information about the commit used for it:

$ shards --version
Shards 0.4.0 (2015-09-25)

I think will be great to have something similar to Crystal itself, where the SHA1 from Git used to build the release is included in the output:

$ crystal --version
Crystal 0.8.0 [e363b63] (Sat Sep 19 12:08:14 UTC 2015)

Thank you.

shard.yml or project.yml ?

  • Shard is a sweet name, but doesn't mean anything by itself.
  • Project is more to the point, but kind of boring.

Require semver as official versioning policy

Officially stating that crystal modules/packages should follow semver versioning (http://semver.org) would greatly increase stability in dependency managing.

Version matching becomes much more deterministic and it's simple to lock in on a version specifically, allow just patch updates, feature updates, or even breaking updates at will.

The project structure of crystal solutions seems to be rather well set and thought through already, so this is the logical thing to do to avoid dependency hells.

Following the semver rules are both simple and rewarding, and there's no benefit to ad hoc versioning schemes.

Why the files is inside of my project?

Why the dependencies need to be inside my project?
For all crystal projects using shards, is really needed to do this?
Is that possible to build some kind of general libs and use this lib on my project just configuring my dependency?

Development dependencies

Event thought shards won't distribute end-user software, contributing to a library and using a library are different matters, and don't necessarily require the same set of libraries. We should thus have development dependencies along with the regular dependencies.

The development dependencies would only be searched and installed for the current project. Shards shall only ever install nested dependencies only.

Only update the specified shards

It would be nice to be able to only update a specified set of shards, instead of everything. The update command would also do its best to only update nested dependencies to satisfy new requirements, keeping as much as possible the locked versions.

$ shards update mock
Using library
Using extra
Updating mock

`.shards` and `libs` directories are always created

I recently noticed that Shards will always create the .shards and libs directories within the current directory. I don't think this is the desired behaviour.

For example, calling shards --version will create both .shards and libs in the current directory:

pwd              #=> /Users/jesse/Desktop
ls -a            #=> . .. .DS_Store .localized
shards --version #=> Shards 0.5.0 (2015-9-30)
ls -a            #=> . .. .DS_Store .localized .shards libs

I solved the issue on my own local fork of Shards by adding a simple Shards::Event module that allows commands to be deferred as such:

Event.defer_until(:install, :update) do |event|
  Dir.mkdir_p(CACHE_DIRECTORY) unless Dir.exists?(CACHE_DIRECTORY)
  Dir.mkdir_p(INSTALL_PATH) unless Dir.exists?(INSTALL_PATH)
end

and:

# in src/commands/install.cr#initialize
Event.announce(:install)

I also think a simple event mechanism may be useful in other situations across the Shards codebase.

Does this approach seem reasonable to you? I'll submit a PR if you agree with it.

fails to build with crystal master

Building with latest crystal (from git master) fails due to changed Process::run overloads.

in ./src/resolvers/git.cr:172: no overload matches 'Process::run' with types String
Overloads are:
 - Process::run(cmd : String, args = nil, env = nil : Env, clear_env = false : Bool, shell = false : Bool, input = false : Stdio, output = fal
se : Stdio, error = false : Stdio, chdir = nil : String | ::Nil)
 - Process::run(cmd : String, args = nil, env = nil : Env, clear_env = false : Bool, shell = false : Bool, input = nil : Stdio, output = nil :
 Stdio, error = nil : Stdio, chdir = nil : String | ::Nil, &block)

        status = Process.run("/bin/sh", input: command, output: capture)
                         ^~~

Error when no branch is speficied

Given the following shard.yml :

name: myproject
version: 0.0.1

dependencies:

    minitest: 
        github: ysbaddaden/minitest.cr

I get this error

Updating https://github.com/ysbaddaden/minitest.cr.git
Index out of bounds (IndexOutOfBounds)
*Exception@Exception#initialize<IndexOutOfBounds, String>:Array(String) +46 [36757184]
*IndexOutOfBounds#initialize<IndexOutOfBounds, String>:Array(String) +6 [36757184]
*IndexOutOfBounds::new<String>:IndexOutOfBounds +97 [36757184]
*IndexOutOfBounds::new:IndexOutOfBounds +16 [36757184]
*String#byte_slice<String, Int32, Int32>:String +756 [36757184]
*String#[]<String, Int32, Int32>:String +82 [36757184]
*String#[]<String, Range(Int32, Int32)>:String +219 [36757184]
*Shards::Package@Shards::Helpers::NaturalSort#natural_sort<Shards::Package, String, String>:Int32 +169 [36757184]
~fun_literal_26 +9 [36757184]
*Array(T)::quicksort!<Pointer(String), Int32, (String, String -> Int32)>:Nil +620 [36757184]
*Array(String)@Array(T)#sort!<Array(String), &(String, String -> Int32)>:Array(String) +49 [36757184]
*Array(String)@Array(T)#sort<Array(String), &(String, String -> Int32)>:Array(String) +37 [36757184]
*Shards::Package@Shards::Helpers::Versions#resolve_versions<Shards::Package, Array(String), Array(String)>:Array(String) +585 [36757184]
*Shards::Package#matching_versions<Shards::Package>:Array(String) +47 [36757184]
*Shards::Package#version<Shards::Package>:String +14 [36757184]
*Shards::Package#spec<Shards::Package>:Shards::Spec +35 [36757184]
*Shards::Manager#resolve<Shards::Manager, Shards::Spec>:Array(Shards::Dependency) +132 [36757184]
*Shards::Manager#resolve<Shards::Manager>:Array(Shards::Dependency) +32 [36757184]
*Shards::Commands::Update#run<Shards::Commands::Update>:Shards::Set +30 [36757184]
*Shards::Commands::update<String>:Shards::Set +14 [36757184]
*Shards::Commands::update:Shards::Set +14 [36757184]
~fun_literal_20 +220 [36757184]
*OptionParser::ParseTask#parse<OptionParser::ParseTask>:Array(String)? +717 [36757184]
*OptionParser#parse<OptionParser, Array(String)>:Array(String)? +147 [36757184]
__crystal_main +26616 [36757184]
main +35 [36757184]
__libc_start_main +245 [36757184]
_start +41 [36757184]
 +41 [36757184]

when trying to install minitest when branch is omitted.
if I add branch:master it installs the dependencies.

Shards should fetch master branch if not specified.

I'm on Debian 4.7.2-5 , x86_64

Packages (DEB, RPM)

Along with the static binaries it would be great to have installable packages. They could be distributed in the official Crystal repositories. They would also distribute the man pages, and depend on official libyaml packages —at least for DEB, since RPM requires an optional channel (eg: rhel-x86_64-server-optional-7).

  • .deb — Debian & Ubuntu
  • .rpm — RHEL & Centos

issues parsing empty Projectfile

Given a dependency that has an empty Projecfile

deps do
end

Seems parse_dependencies_from_projectfile provides an empty array ([]) that results directly concatenated to the spec file:

name: beryl\n[]

Instead of being prepend with dependencies.

I solved that by setting dependencies as empty string:

diff --git a/src/resolvers/git.cr b/src/resolvers/git.cr
index 422a041..ff4a548 100644
--- a/src/resolvers/git.cr
+++ b/src/resolvers/git.cr
@@ -30,6 +30,8 @@ module Shards

           if dependencies.any?
             dependencies = "dependencies:\n#{dependencies.join("\n")}"
+          else
+            dependencies = ""
           end
         end

But I wasn't sure about the proper test for this, which is why I submit an issue and not a pull request, sorry 😞

Thank you.
❤️ ❤️ ❤️

TOML vs YAML vs JSON

Continuing from crystal-lang/crystal#1357 and crystal-lang/crystal#220 we may decide to use another format than YAML. I tried to summarize the different pros & cons:

  • YAML:
    • pro: stable standard + available in Crystal's stdlib
    • pro: simple to write/read manually
    • pro: canonical serialization for automated tooling
      • con: but likely to wreck the original formatting
    • pro: yaml_mapping is likely to happen
    • con: some strings must be quoted (eg: ~>)
    • con: format much more complex than required
  • TOML:
    • pro: used by Rust's Cargo
    • con: standard not quite stable + not in crystal's stdlib (thought there is crystal-toml)
    • con: format can be weird for the neophyte
    • con: toml_mapping is unlikely to happen
    • con: requires to quote all strings
  • JSON:
    • pro: simple enough format
    • pro: standard serialization for automated tooling (not likely to wreck original formatting)
    • pro: json_mapping
    • con: complex to write/read manually

Build on OSX?

Would love to try using shards, but I'm unable to get it to build on OSX 10.10.4.

When running make all I get:

$ make all
`which crystal` build -o bin/shards src/shards.cr
ld: library not found for -lyaml
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Error: execution of command failed with code: 1: `cc -o bin/shards "/Users/spencer/dev/shards/.crystal/... {hundreds of files} -lyaml -levent -lpcl -lpcre -lgc -lpthread

I'm running Crystal 0.7.4 [42efdbf] (Wed Jun 24 00:55:53 UTC 2015) installed from https://github.com/manastech/homebrew-crystal with brew, and also have libyaml installed and properly (to brew's standards) linked.

Any ideas what's missing?

Smarter dependency resolver

The current dependency resolver is dumb.

It takes the current project shard.yml then clones dependencies, extracts the available versions and takes the shard.yml for the latest version matching the requirement (or HEAD).

It then does the same for the dependencies of each dependency, pushing new dependencies or requirements to a flat list of packages, and so on, recursively.

If any package in the flattened list packages and requirements can't eventually be resolved to at least one version, the resolver will fail by raising a conflict.

This resolver should work for quite some time, until Crystal starts having lots of libraries with lots of dependencies, in which case it will quickly fail.

A smarter resolver will then be appreciable.

Should the .shards folder be excluded from the repository

When shards is run, it puts all package data into a .shards folder within the project where it is run.

Should the .shards folder be added to my .gitignore so as to exclude it from my git repository?

If I pull the code onto another system, I think I'll need to run shards install before the associated shards are enabled on the local system - and as this will recreate the .shards folder, is there any point having the .shards folder in the repository.

What is the best strategy?

Integration Tests when locking a Git refs (branch, tag)

When a dependency references a Git refs (ie. branch or tag or commit) we should have tests that make sure that:

  • it actually locks a commit refs (and not the branch, tag or version)
  • it installs the dependency at the locked commit (and not the branch, tag or version)
  • upgrade locks a new commit

Tag 'v1.2.3' vs '1.2.3'

Repositories are expected to have version tags, using the v1.2.3 format, this example matching version 1.2.3 of a library.

Minor question, so would this allow a tag named 1.2.3 too or not? If not, I think it should. Any potential problems you know with doing so?

Shards for Idiots -- like me.

I'm a ruby developer who wants to write a simple executable and likes the idea of using this as a first Crystal project. I much prefer minitest to spec, so I'd like to use minitest.cr with my new project. It looks like shards should give me the facility to incorporate minitest.cr into my crystal project.

What I can't work out is how to bring the three elements together: crystal, shards, and minitest. Specifically, how do I install shards locally on my system (I'm using linux - xubuntu), and then how do I get my crystal environment to use it?

Comparing crystal to ruby

It seems to me that shard.yml is the equivalent of Gemfile.yml in ruby

What I'm not sure about is what are the equivalents to:

Installing

What is the shards equivalent of either:
sudo apt-get install rubygems
and/or
gem install bundler

Running

What is the shards equivalent to:
gem install <gem-name>
or
bundle install

I presume the latter is actually what I'm after as the Gemfile.yml to shard.yml usage implies to me that shards is to crystal what bundler is to ruby (rather than rubygems to ruby)

Please forgive me if this seem a little too "Crystal for beginners" but as follower of the sage that is Scott Adams, I know I am just a poor idiot

make error on osx

/usr/local/bin/crystal build -o bin/shards src/shards.cr
Error in ./src/cli.cr:23: instantiating 'OptionParser:Class#parse!()'

  OptionParser.parse! do |opts|
               �[32;1m^~~~~~�[0m

in /usr/local/Cellar/crystal-lang/0.7.7/src/option_parser.cr:54: instantiating 'parse(Array(String))'

    parse(ARGV) { |parser| yield parser }
    �[32;1m^~~~~�[0m

in /usr/local/Cellar/crystal-lang/0.7.7/src/option_parser.cr:54: instantiating 'parse(Array(String))'

    parse(ARGV) { |parser| yield parser }
    �[32;1m^~~~~�[0m

in ./src/cli.cr:23: instantiating 'OptionParser:Class#parse!()'

  OptionParser.parse! do |opts|
               �[32;1m^~~~~~�[0m

in ./src/cli.cr:34: instantiating 'Shards::Commands:Module#check()'

        Shards::Commands.check
                         �[32;1m^~~~~�[0m

instantiating 'check(String)'

in ./src/commands/check.cr:29: instantiating 'Shards::Commands::Check:Class#new(String)'

      Check.new(path).run
            �[32;1m^~~�[0m

instantiating 'Shards::Commands::Check#initialize(String)'

in ./src/commands/check.cr:11: instantiating 'Shards::Spec:Class#from_file(String)'

        @spec = Spec.from_file(path)
                     �[32;1m^~~~~~~~~�[0m

in ./src/spec.cr:12: instantiating 'from_yaml(String)'

      from_yaml(File.read(path))
      �[32;1m^~~~~~~~~�[0m

in ./src/spec.cr:18: �[1mundefined constant TypeCastError�[0m

    rescue TypeCastError
           �[32;1m^~~~~~~~~~~~~�[0m

I'm getting this error while trying to run make or make release. I added /opt/homebrew/lib to $LIBRARY_PATH, but I later realised that is non-existent directory on my system. I found libyaml inside /usr/local/Cellar. Adding that to the path also doesn't seem to solve the problem.

shards fails hard when trying to run shards check before install

trace: strace -f -o out shards check; grep chdir out

Error while changing directory: No such file or directory (Errno)
[94086811318359] *CallStack::unwind:Array(Pointer(Void)) +87
[94086811318250] *CallStack#initialize<CallStack>:Array(Pointer(Void)) +10
[94086811318202] *CallStack::new:CallStack +42
[94086811338223] *Exception +31
[94086811338164] *Errno#initialize<Errno, String>:CallStack +132
[94086811337988] *Errno::new<String>:Errno +100
[94086811413268] *Dir::chdir<String>:Nil +36
[94086811532870] *Shards::GitResolver+ +406
[94086811532454] *Shards::GitResolver+ +22
[94086811532335] *Shards::GitResolver+ +47
[94086811532271] *Shards::GitResolver+ +47
[94086811530209] *Shards::GitResolver+ +385
[94086811484585] *Shards::Package#available_versions<Shards::Package>:Array(String) +153
[94086811484382] *Shards::Package#matching_versions<Shards::Package>:Array(String) +14
[94086811484286] *Shards::Package#version<Shards::Package>:String +14
[94086811484157] *Shards::Package#spec<Shards::Package>:Shards::Spec +29
[94086811526880] *Shards::Manager#resolve<Shards::Manager, Array(Shards::Dependency), Bool>:Array(Shards::Dependency) +144
[94086811526734] *Shards::Manager#resolve<Shards::Manager, Shards::Spec>:Array(Shards::Dependency) +30
[94086811526603] *Shards::Manager#resolve<Shards::Manager>:Array(Shards::Dependency)? +27
[94086811513435] *Shards::Commands::Check#run<Shards::Commands::Check>:(Nil | Int32) +27
[94086811513097] *Shards::Commands::check<String>:(Nil | Int32) +25
[94086811513046] *Shards::Commands::check:(Nil | Int32) +22
[94086811263222] ~fun_literal_35 +134
[94086811572569] *OptionParser::ParseTask#parse<OptionParser::ParseTask>:Array(String)? +713
[94086811510051] *OptionParser#parse<OptionParser, Array(String)>:Array(String)? +147
[94086811247432] ???
[94086811256768] main +32
[140011427907088] __libc_start_main +240
[94086811219705] _start +41
[0] ???
19230 chdir("/home/jokke/code/projects/rofi-curses/.shards/ncurses") = -1 ENOENT (No such file or directory)
19230 chdir("/home/jokke/code/projects/rofi-curses") = 0

Integration with crystalshards

This would be super helpful for crystalshards, since it would make shard discovery super easy, opposed to searching for crystal project using GitHub's API, which is what we're doing right now.

I had mentioned to @asterite that at some point it would be good to have some sort of registry, if for nothing else, for the metadata of projects, so you can better and easily analyse the libs landscape.

Do you plan on storing the binaries for each version, eventually? Will I have to register a shard somewhere (I'm assuming yes)?

Error with git version 1.7.9.5

When I tried to run shards install after installing shards on an unbuntu system, I got the following error:

git command failed: git tag --list --no-column

Updating my version of git solved the problem.

It appears that the --no-column option came in at version 1.7.11 and I was using 1.7.9.5. When I upgraded git, the new version was 2.5.

make test can run integration & unit test suite in parallel

And that blows up most of the time since one deletes directories the other creates or vice versa. One can workaround with make -j1 test but it would be nice to have a Makefile (or otherwise) setup that prevents running them at the same time in the first place.

New command: outdated

The command shall list the outdated shards (and only them) along with the installed version, the available version (matching the requirements) and the latest version.

$ shards outdated
pg (0.3.0, available: 0.3.2, latest: 0.4.0)
minitest (0.1.3, available: 0.1.5)

make release on OSX

/usr/local/bin/crystal build --release -o bin/shards src/shards.cr --link-flags "-static -L/opt/crystal/embedded/lib"
ld: warning: directory not found for option '-L/opt/crystal/embedded/lib'
ld: library not found for -lcrt0.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Error: execution of command failed with code: 1: `cc -o "bin/shards" "${@}" -static -L/opt/crystal/embedded/lib -rdynamic  -lyaml -levent -lpcl -lpcre -lgc -lpthread -ldl`
make: *** [release] Error 1

install should install and update according to the .lock

Let's have a project and a library

$ tree
├── libs
│   └── library
│       └── shard.yml
├── shard.lock
└── shard.yml
$ cat shard.yml
name: "project"
version: 0.1.0
dependencies:
  library:
    git: ../../library
    branch: master
$ cat shard.lock
version: 1.0
shards:
  library:
    git: ../../library
    commit: 1c5d802a00011557294c15eef52f387a0d551f23
$ cd ..
$ git --git-dir=library/.git log --oneline -1
6b0b9e8 new file

Let's clone our project to install it somewhere else:

$ git clone project clone
$ cd clone
$ shards
Updating ../../library
Updating ../../library
Updating ../../library
Updating ../../library
Updating ../../library
Installing library (1c5d802a00011557294c15eef52f387a0d551f23)
Updating ../../library
Updating ../../library
$ tree
Updating ../../library
Updating ../../library
Updating ../../library
Updating ../../library
Updating ../../library
Installing library (1c5d802a00011557294c15eef52f387a0d551f23)
Updating ../../library
Updating ../../library
$ tree
.
├── libs
│   └── library
│       ├── library.cr
│       ├── new_file.cr
│       └── shard.yml
├── shard.lock
└── shard.yml
$  cat shard.lock
version: 1.0
shards:
  library:
    git: ../../library
    commit: 1c5d802a00011557294c15eef52f387a0d551f23

Okay, first bug, lock is still the same, output has claimed to install 1c5d802a, actually installed is 6b0b9e8.

Let's get rid of that clone, update the lock to 6b0b9e8 and clone and install again.

$ cd ..
$ rm -rf clone
$ cd project
$ shards

Mkay, we called install, lock stays the same but the worktree is the updated version again. But that's probably the same bug as above. Time to update the lock. Then let's clone our project again and install

$ shards update
$ git commit -am "update library"
$ cd ..
$ git clone project clone
$ cd clone
$ shards

Everything good so far. Time to fix something in the library.

$ cd ..
$ cd library
$ touch src/fix.cr
$ git add src
$ git commit -m "fix"
$ cd ../project
$ shards update
$ git commit -am "update library again"
$ cd ../clone
$ git pull
$ shards
Updating ../../library
Updating ../../library
Updating ../../library
Updating ../../library
Updating ../../library
Using library (94417f573623cce28f69d26fdf1dc09cccd75b2d)
$ tree
.
├── libs
│   └── library
│       ├── library.cr
│       ├── new_file.cr
│       └── shard.yml
├── shard.lock
└── shard.yml

2 directories, 5 files

And now we got the above bug in reverse, install claimed it installed 94417f5 but the worktree wasn't updated.

Update fails after attempting to resolve dependency that is missing shard spec

If you specify a Github dependency that is missing a shard spec (? shard.yml), the dependency resolver will fail as expected:

Updating https://github.com/will/crystal-pg.git
cd /home/nitrous/.shards
git clone --mirror --quiet -- 'https://github.com/will/crystal-pg.git' crystal-pg
cd /home/nitrous/.shards/crystal-pg
git tag --list --contains master
cd /home/nitrous/.shards/crystal-pg
git ls-tree -r --full-tree --name-only v0 -- shard.yml
fatal: Not a valid object name v0
git command failed: git ls-tree -r --full-tree --name-only v0 -- shard.yml

If you then correct the dependency (such as pointing to another repository, in my case a forked repository that includes a shard spec) and run shards again, the dependency resolver will still fail:

Updating https://github.com/jbye/crystal-pg.git
cd /home/nitrous/.shards/crystal-pg
git fetch --all --quiet
cd /home/nitrous/.shards/crystal-pg
git tag --list --no-column
can't resolve crystal-pg (0.1.0)

This seems to be caused by the .shards/crystal-pg directory created when the resolver ran for the invalid dependency spec. If I remove the .shards/crystal-pg directory and re-run shards it succeeds.

New command: prune

This command shall remove any installed dependency from the libs folder that isn't required by the current shard.yml (and shard.lock).

$ shards prune
pruned libs/mock (0.1.0)
pruned libs/extra (1.2.3)

Integration tests

In order to properly test the lock file behavior , integration tests are required. They would use the compiled shards binary and generate/manipulate different shard.yml in different project folders and test the outcome (what dependencies are installed, failures, if it correctly uses the lock file, updates the dependencies and lock file, ...)

refs #12 and #27

.shardspec could be useful

First off: I'm glad this was incorporated into Crystal.

Would it be desirable to add something like Ruby's .gemspec? I find that really useful to differentiate gems from projects. Also, it's actually Ruby code which gets evaluated, therefore there's no need to supply the version twice (once in a module's version.cr and once in the shards.yml file.)

Example:

# bson.shardspec

require "./src/bson/version"

Shard::Specification do |spec|
  spec.version = BSON::Version
  # ... other useful stuff once/if there's a registry
end

Error when dependency lacks version (legacy Projectfile)

Hello,

Testing against latest master, Shards fails to parse Projectfile as legacy.

Example:

name: testing
version: 0.0.1

dependencies:
  routing:
    github: bcardiff/crystal-routing
    branch: master

Results in the following output:

in shard.yml:1: Shards::ParseError: missing required attribute: version at 1:0

  1. name: routing
     ^

In this particular case I believe the issue is introduced by the lack of version tags in the dependency repository, but not sure.

Thank you.

Dependency free project generates invalid lock

Or "Empty lockfile is invalid", depending on the viewpoint ;)

$ echo "name: foo" > shard.yml
$ shards
$ shards
Invalid shard.lock. Please delete it and run install again.
$ cat shard.lock
version: 1.0
shards:

Add support for c libraries.

One possible way to add c library support:

  1. A build command (or list of commands) in shard.yml
  2. State tracking and output capture of commands for debugging (similar to rubygems).
  3. Additional library path injection to the crystal build process. shards.yml could contain additional c library paths. Minor modification of crystal may be necessary to read the list of additional library paths.

New command: init

crystal init creates a whole project structure. That's not always wanted, especially when turning an existing project into a shard. shards init should write a simple example shard.yml to the current git repositories root.

Generate default shard.yml when missing

Shards is relatively new and crystal projects don't use it, yet. I hope this will eventually change, but in the meantime shards should do its best to generate default shard.yml when libraries don't provide one.

Thus, resolvers should:

  • return a minimal name: <name>\nversion: 0\n
  • parse Projectfile (if present) and extract dependencies
  • guess the version, using GitResolver#version_at(refs) (note that PathResolver won't be able to guess)

refs #4

Usage and binaries

Would it work like gem, in that you have both Ruby and Gem executables which both have different usage, or, will this eventually be integrated back the the compiler ? like how deps are now ?

Lock dependencies

Shards is missing a mechanism to lock the state of installed dependencies, so installs could be repeatable, always installing the same exact set of dependencies across developer machines, CI, ...

The format of the lock file is undecided. I think it should contain the flattened list of dependencies, along with their Git URL and either the version or Git commit (if a git tag/commit/branch refs is specified).

The lock file will impact the install command which must abide to the locked versions/refs and do its best to install new dependencies that match. The lock file may be seen as an initial set of requirements for dependencies —yet not be injected as dependencies, which could install removed dependencies.

The update command must not be impacted, but must generate the lock file.

Cryptic error messages on invalid shard.yml format

Just upgraded to Crystal 0.8.0 and getting a typeCast error

cast to Hash(K, V) failed (TypeCastError)
[4350108354] *CallStack::unwind:Array(Pointer(Void)) +82
[4350108257] *CallStack#initialize<CallStack>:Array(Pointer(Void)) +17
[4350108216] *CallStack::new:CallStack +40
[4350164081] *Exception@Exception#initialize<TypeCastError, String>:CallStack +33
[4350164013] *TypeCastError#initialize<TypeCastError, String>:CallStack +29
[4350163953] *TypeCastError::new<String>:TypeCastError +97
[4350258710] *Shards::Spec#to_dependencies<Shards::Spec, (Nil | String | Array(YAML::Type) | Hash(YAML::Type, YAML::Type))>:Array(Shards::Dependency) +294
[4350258398] *Shards::Spec#dependencies<Shards::Spec>:Array(Shards::Dependency) +46
[4350281076] *Shards::Manager#resolve<Shards::Manager, Shards::Spec>:Array(Shards::Dependency) +20
[4350280957] *Shards::Manager#resolve<Shards::Manager>:Array(Shards::Dependency)? +29
[4350325664] *Shards::Commands::Install#run<Shards::Commands::Install>:Array(Shards::Package)? +32
[4350256593] *Shards::Commands::install<String>:Array(Shards::Package)? +17
[4350256570] *Shards::Commands::install:Array(Shards::Package)? +26
[4350057846] ~fun_literal_29 +182
[4350332010] *OptionParser::ParseTask#parse<OptionParser::ParseTask>:Array(String)? +634
[4350247862] *OptionParser#parse<OptionParser, Array(String)>:Array(String)? +134
[4350043935] __crystal_main +27471
[4350053184] main +32

Here's my shard.yml

name: amethyst
version: 0.1.7

dependencies:
  github: spalger/crystal-mime
  branch: master

Upload binaries for 0.5.2

We install the latest release of shards on Travis automagically, but that depends on having binaries for the latest release.

OS X support

Is this planned? I tried getting started but compile errors.

➜  shards git:(master) crystal build src/shards.cr
ld: library not found for -lyaml
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Error: execution of command failed with code: 1: `cc -o "shards" "${@}"  -rdynamic  -lyaml -levent -lpcl -lpcre -lgc -lpthread -ldl`

Thought I would try this language out and tinker with Moonshards but I couldn't get shards installed. When I get home I'll install it on my Arch box but, you know.

Error when executing `shards` a second time with a Projectfile dependency

Hello,

This issue is related to #52, and seems to occur not when installing dependencies, but subsequent commands runs against the generated lockfile.

The following shard.yml is able to reproduce it:

name: testing
version: 0.0.1

dependencies:
  routing:
    github: bcardiff/crystal-routing
    branch: master

On first run (no .shards, libs or shard.lock exist):

$ shards --version
Shards 0.5.0 [a501f92] (2015-09-28)
$ shards install
Updating https://github.com/bcardiff/crystal-routing.git
Installing routing (master)

On second run:

$ shards install
Updating https://github.com/bcardiff/crystal-routing.git
in shard.yml:1: Shards::ParseError: missing required attribute: version at 1:0

  1. name: routing
     ^

On removal of libs:

$ shards install
Updating https://github.com/bcardiff/crystal-routing.git
Installing routing (2289be7382ee027c0905e5c56523356345e46541)

And second run:

$ shards install
Updating https://github.com/bcardiff/crystal-routing.git
in shard.yml:1: Shards::ParseError: missing required attribute: version at 1:0

  1. name: routing
     ^

Notice the difference between the first install (pointed to master and the second (when using the commit from shard.lock)

However, the error around missing version cannot be avoided unless .shards directory is removed and dependency cloned again, at which point the issue repeats again.

This also happens when invoking check too:

$ rm -rf .shards/ libs/

$ shards check
Dependencies aren't satisfied. Install them with 'shards install'

$ shards install
Updating https://github.com/bcardiff/crystal-routing.git
Installing routing (2289be7382ee027c0905e5c56523356345e46541)

$ shards check
in shard.yml:1: Shards::ParseError: missing required attribute: version at 1:0

  1. name: routing
     ^

This only happens with legacy dependency (Projectfile).

Thank you.

New command: list

The command shall list all dependencies, along with their locked version.

$ shards list
pg (0.3.2)
minitest (0.1.5)

Fails to install with locked GIT commit targetting older commit of targetted refs

The following integration test fails with "outdated shard.lock" when running shards install because Shards considers available versions to be ["master", "v2.1.0"] instead of checking if the locked commit is contained by the master branch.

  def test_installs_dependencies_at_locked_commit
    metadata = {
      dependencies: { web: { branch: "master" } }
    }
    lock = { web: git_commits(:web)[2] }

    with_shard(metadata, lock) do
      run "shards install"
      assert_installed "web", "v1.1.1"
    end
  end

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.