I have a Gem I'm developing - My Gemspecs builds the files for the gem from git:
spec.files = `git ls-files -z`.split("\x0")
The Gem itself has an empty directory in the lib folder, which i've added a .keep to preserve via git
my_gem/
- lib/
- some_empty_folder/
- .keep
But when I install the gem to my system I see that some_empty_folder gets removed.
According to specification refrence: http://guides.rubygems.org/specification-reference/#files
files
Files included in this gem. You cannot append to this accessor, you
must assign to it.
Only add files you can require to this list, not directories, etc.
Directories are automatically stripped from this list when building a
gem, other non-files cause an error.
I was hoping the .keep file would preserve this empty structure, but I've hacked around it by adding an empty .rb file. What is the best way to work around this issue?
Instead of the .keep, you could instead add a .gitignore to the empty folder.
# Ignore all items in this directory
*
# Except this .gitignore file
!.gitignore
This will always preserve that folder as an empty structure.
Related
This might be really naive as I have never had to do this before but is there a way to generate a .gemspec file from a .gem? Like the opposite of gem build xxx.
A .gem file is basically a .tar archive. Inside this .tar archive you will have 2 important files:
data.tar.gz - containing the source code and possibly a .gemspec file (this is not a guarantee though)
metadata.gz - basically a .gemspec, but in a YAML format which you won't be easily able to convert back
I've never built my own gem before, so this is a totally new experience. I've built a library for my employer, which has to connect to a database of ours in order to run some of my tests. I want to make sure this config.yml file isn't included in the gem when I publish it. I've added it to the .gitignore file, as I know to do that, but is there some other change I have to make to the .gemspec maybe? Or does bundler only include files it knows about when releasing the library to the public? Just trying to be cautious, first time publishing open source code!
Specification after #Oleander replied:
Running git ls-files in the command line doesn't include the file I want to remove, and my spec.require_paths in the .gemspec file reads like this: ["lib"]. The spec directory isn't there. Does that mean the config.yml file won't be included when I release the gem?
Remove config.yml from s.files in your project.gemspec file inside your project and the file wont show up in your .gem-file.
s.files = `git ls-files`.split($/)
s.files -= ["spec/config.yml"]
I'm currently attempting to create a ruby gem out of a script and, while it works if I take the scripts and put them in the same directory, if I put them in the appropriate /bin and /lib directories after generating my gem structure, build the gem and then attempt to execute it I'm given the uninitialized constant error. Under /bin the relevant section in the file "cjp" is:
Cjb.new(crontabDir, logDir, allowedFrequency, printOnly, testRun).
find_violations autoFix
The class is defined in the file cjp.rb under /lib
class Cjb
def initialize(crontabDir, logDir, allowedFrequency, printOnly, testRun)
#crontabDir, #logDir, #allowedFrequency, #printOnly, #testRun =
crontabDir, logDir, allowedFrequency, printOnly, testRun
Despite this, the error I get is:
ERROR: uninitialized constant Cjb
I also noticed that if I attempt to manually execute the "cjp" script under /bin without the lib script being in the same directory that it also gives the same error. It appears that I'm missing something.
Any help on what I'm missing here to get this working would be appreciated.
bundle gem uses git to manage gem manifest.
If you do not see all your expected files when you run git ls-files in your gem project dir, then you need to add them.
To add individual files:
git add <filename>
To add everything (run from root of project):
git add .
This may have caught you out if you were not expecting to use git on your project. If you don't know git, and have time, it is really recommended to help you manage your project code. In fact so much so that bundle simply assumes that's what you want to do (although other code management tools are available)
TL;DR:
Don't run bundle within an existing git repository. Weird things will happen without any error messages.
Original Question:
I've built a gem by adapting the steps in this tutorial:
http://net.tutsplus.com/tutorials/ruby/gem-creation-with-bundler/
As a final step, I've run gem build .gemspec
This succeeds, but when I install the gem I find the critical file, the one which contains my code, isn't in the gem. Another file in the same (lib) directory, "version.rb", does exist in the gem.
I don't know how to start debugging this...how does bundler/gem build decide which files to include in the gem?
Edit:
My workflow is:
gem build <project_name>.gemspec
gem unpack <project_name>
=> confirm file does not exist in <unpacked>/lib/
gem install <project name>
=> confirm file structure in ~/home/stefan/.rvm/... contains gem, but does not contain desired file
Edit 2 / Resolution:
I was finally able to get this working by committing all my code to a remote repository, creating a clean clone, and building the gem. The new gem included all the required files.
A bit of history...I originally created the code and committed it before thinking about making a gem (this is my first gem). I then used bundle inside the original repository, which didn't complain, but was probably the reason for the weirdness.
One of the things bundler did for you is start a local git repo to version-manage your gem code. Check that you have added the file in git
git add lib/gem_name/missing_file.rb
Bundler generated gems use git internally to track "membership" of source files for the gem. You can see this in the .gemspec where it uses backticks to call out to git and generate a file list:
gem.files = `git ls-files`.split($/)
Note this also means you should pay attention to what you list in .gitignore
I've got a custom gem that has been working just fine with regards to bundling, building, distributing, & implementing. The gem is the core of a framework from which other gems are derived. Since most derived gems will have the same basic structure, I want to include a Ruby script in the bin path of the gem that can be used to basically copy files from a template folder into a new folder where the user will develop their own gem.
The problem I'm having is that the template folder has a gemspec file named $name$.gemspec with similarly named classes/modules in the file (e.g.: module $Name$), where the $name$ gets replaced with a name provided by the user.
Unfortunately, when I run bundle install from my gem's top-most path, I get an error:
There was a SyntaxError while evaluating $name$.gemspec:
C:/my_gem/template/$name$.gemspec:8: syntax error, unexpected tGVAR
gem.version = MyGem::$Name$::VERSION
It looks like Bundler is using the wrong Gemfile, even if I explicitly pass the Gemfile or path via one of the following:
bundle install --gemfile=Gemfile
bundle install --path=C:\my_gem
I also tried updating the gemspec line of my Gemfile to no avail:
gemspec name: 'my_gem'
Lastly, I've ensured that the template folder isn't even included in my_gem.gemspec, but that doesn't seem to matter:
gem.files = Dir.glob("lib/**/*") + %w(LICENSE.txt README.md)
Does anyone know why Bundler is trying to read the ./template/$name$.gemspec instead of ./my_gem.gemspec?
Inspecting the Bundler source, I may have spotted the culprit in lib/bundler/source/path.rb. There's GLOB used to find gemspecs in load_spec_files. The default glob is "{,*,*/*}.gemspec". This will find *.gemspec in the root directory of your gem or any directory one descendant from root (which will include your template dir).
If this is indeed the culprit, you could work around this by placing your template directory deeper in your gem's dir hierarchy or changing the name of the template file so it doesn't end in .gemspec. The Bundler::Source::Pathobject looks like it can take a different glob at initilization but I haven't dug deep enough to see if there's a viable way to specify this alternative glob in bundle execution via config or cmdline options.