Skip to content

Commit

Permalink
Initial project import
Browse files Browse the repository at this point in the history
  • Loading branch information
bosko committed Jun 8, 2012
0 parents commit 80df64e
Show file tree
Hide file tree
Showing 8 changed files with 316 additions and 0 deletions.
23 changes: 23 additions & 0 deletions .autotest
@@ -0,0 +1,23 @@
# -*- ruby -*-

require 'autotest/restart'

# Autotest.add_hook :initialize do |at|
# at.extra_files << "../some/external/dependency.rb"
#
# at.libs << ":../some/external"
#
# at.add_exception 'vendor'
#
# at.add_mapping(/dependency.rb/) do |f, _|
# at.files_matching(/test_.*rb$/)
# end
#
# %w(TestA TestB).each do |klass|
# at.extra_class_map[klass] = "test/test_misc.rb"
# end
# end

# Autotest.add_hook :run_command do |at|
# system "rake build"
# end
6 changes: 6 additions & 0 deletions History.rdoc
@@ -0,0 +1,6 @@
=== 1.0.0 / 2012-05-30

* 1 major enhancement

* Birthday!

9 changes: 9 additions & 0 deletions Manifest.txt
@@ -0,0 +1,9 @@
.autotest
History.rdoc
Manifest.txt
README.rdoc
Rakefile
lib/rubygems_plugin.rb
lib/rubygems/commands/exefy_command.rb
lib/templates/gem_exe.c
test/test_gem_exefy.rb
74 changes: 74 additions & 0 deletions README.rdoc
@@ -0,0 +1,74 @@
= gem-exefy

code :: http://github.com/bosko/gem-exefy
bugs :: http://github.com/bosko/gem-exefy/issues

== DESCRIPTION:

GemExefy is RubyGems plugin aimed to replace batch files (.bat) with executables with same name.

Rationale behind this is described in this message https://groups.google.com/forum/?fromgroups#!topic/rubyinstaller/fQCuPfiuuRc

GemExefy searches following directories for batch files

- Gem.bindir
- Gem.path

Since Gem::path array contains directories pointing to the top level directory and executables are saved in the Gem#bindir folder, GemExefy concatenates directory from Gem.path with value of Gem#bindir (bin directory defined in the target Gem) and name from Gem#executables array with .bat extension. If such file is found it is replaced with corresponding executable file with same name and .exe extension.

Backup of old batch files will be made if '-b' option is used. Otherwise they will be deleted.

== FEATURES/PROBLEMS:

* No known problems at the moment

== SYNOPSIS:

C:\> gem exefy <gem_name>

or:

C:\> gem exefy <gem_name> -b

== REQUIREMENTS:

* RubyInstaller Ruby version
* RubyInstaller's DevKit

== INSTALL:

* gem install gem-exefy

== DEVELOPERS:

After checking out the source, run:

$ rake newb

This task will install any missing dependencies, run the tests/specs,
and generate the RDoc.

== LICENSE:

(The MIT License)

Copyright (c) 2012 FIX

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 changes: 23 additions & 0 deletions Rakefile
@@ -0,0 +1,23 @@
# coding: utf-8
# -*- ruby -*-

require 'rubygems'
require 'hoe'

Hoe.spec 'gem-exefy' do
developer('Boško Ivanišević', 'bosko.ivanisevic@gmail.com')

self.urls = {"GitHub repository" => "http://github.com/bosko/gem-exefy"}
self.readme_file = 'README.rdoc'
self.history_file = 'History.rdoc'
self.extra_rdoc_files = FileList['*.rdoc']
self.require_rubygems_version(">= 1.8.0")
self.version = "0.0.1"
self.post_install_message = %Q{**************************************************
Thank you for installing #{self.name}-#{self.version}!
**************************************************}
end

# vim: syntax=ruby
100 changes: 100 additions & 0 deletions lib/rubygems/commands/exefy_command.rb
@@ -0,0 +1,100 @@
require "rubygems/command"
require "tmpdir"

module Gem
module Commands
class ExefyCommand < Gem::Command
def initialize
super 'exefy', "Replaces Gem's batch file with executable file (Windows only)"
add_option('-b', '--backup-batch-files',
'Keep backup of old batch files') do |value, options|
options[:backup_batch_files] = value
end
end

def execute
unless RUBY_PLATFORM =~ /mingw/
say "This command can be executed only on Windows OS"
return
end

get_all_gem_names.each do |name|
begin
cur_gem = Gem::Specification.find_by_name(name)
batch_files(cur_gem).each do |k,v|
generate_exe(k, v)
end
rescue Gem::LoadError => e
say "Cannot exefy. Gem #{name} not found"
end
end
end

def batch_files(gem)
bf = {}
test_paths = Gem.path.map {|gp| File.join(gp, gem.bindir)}.unshift(Gem.bindir)
gem.executables.each do |executable|
test_paths.map {|tp| File.join(tp, "#{executable}.bat")}.each do |bat|
bf[executable] = [] unless bf[executable]
bf[executable] << bat if File.exist?(bat)
end
end
bf
end

def generate_exe(executable, batch_files)
log_message "Generating exe file"

exefier_src_path = File.join(File.expand_path("../../../templates", __FILE__), "gem_exe.c")
Dir.mktmpdir do |build_dir|
# First create executable for all batch files (it is same .exe file but
# batch files are found in different directories).
targets = Hash[*['c', 'o', 'exe'].map { |ext| [ext, File.join(build_dir, "#{executable}.#{ext}")]}.flatten]
FileUtils.cp exefier_src_path, targets["c"]
compile(targets["c"], targets["o"])
link(targets["o"], targets["exe"])

batch_files.each do |bf|
log_message "Copying exe file to #{File.dirname(bf)}..."
FileUtils.cp targets["exe"], File.dirname(bf)
if options[:backup_batch_files]
log_message "Creating backup of old batch file"
File.rename(bf, "#{bf}.bcp")
else
File.rm bf
end
end
end
end

def compile(source, target)
cflags = RbConfig::CONFIG["CFLAGS"]
cppflags = RbConfig::CONFIG["CPPFLAGS"]

hdr_dir = RbConfig::CONFIG["rubyhdrdir"]
arch_dir = RbConfig::CONFIG["arch"]

include_dirs = "-I#{hdr_dir}/#{arch_dir} -I#{hdr_dir}"

cc = ENV.fetch("CC", RbConfig::CONFIG["CC"])

system "#{cc} -c #{source} -o #{target} #{cflags} #{cppflags} #{include_dirs}"
end

def link(objs, target)
libruby_dir = RbConfig::CONFIG["libdir"]
libruby = RbConfig::CONFIG["LIBRUBYARG"]

libs = RbConfig::CONFIG["LIBS"]
libs_dir = "-L#{libruby_dir} #{libruby} #{libs}"

cc = ENV.fetch("CC", RbConfig::CONFIG["CC"])
system "#{cc} #{objs} -o #{target} #{libs_dir}"
end

def log_message(message)
say message if Gem.configuration.really_verbose
end
end
end
end
3 changes: 3 additions & 0 deletions lib/rubygems_plugin.rb
@@ -0,0 +1,3 @@
require "rubygems/command_manager"

Gem::CommandManager.instance.register_command :exefy
78 changes: 78 additions & 0 deletions lib/templates/gem_exe.c
@@ -0,0 +1,78 @@
#include "ruby.h"
#include <stdlib.h>

#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif

#ifndef MAXPATHLEN
# define MAXPATHLEN 1024
#endif

void
dump_args(int argc, char **argv)
{
int i;
printf("Number of arguments: %d\n", argc);

for (i = 0; i < argc; ++i)
printf("Argument %d: %s\n", i, argv[i]);

printf("=================\n");
}

int
main(int argc, char **argv)
{
#ifdef HAVE_LOCALE_H
setlocale(LC_CTYPE, "");
#endif

int i;
int myargc;
char** myargv;
char script_path[MAXPATHLEN];
char* dump_val;

dump_val = getenv("EXEFY_DUMP");

if (GetModuleFileName(NULL, script_path, MAXPATHLEN)) {
for (i = strlen(script_path) - 1; i >= 0; --i) {
if (*(script_path + i) == '.') {
*(script_path + i) = '\0';
break;
}
}

DWORD attr = GetFileAttributes(script_path);
if (attr == INVALID_FILE_ATTRIBUTES) {
printf("Script %s is missing!", script_path);
return -1;
}
// Let Ruby initialize program arguments
ruby_sysinit(&argc, &argv);

// Change arguments by inserting path to script file
// as second argument (first argument is always executable
// name) and copying arguments from command line after it.
myargc = argc + 1;
myargv = (char**)xmalloc(sizeof(char*) * (myargc + 1));
memset(myargv, 0, sizeof(char*) * (myargc + 1));
*myargv = *argv;
*(myargv + 1) = &script_path[0];

for (i = 1; i < argc; ++i) {
*(myargv + i + 1) = *(argv + i);
}

if (NULL != dump_val) {
dump_args(myargc, myargv);
}

{
RUBY_INIT_STACK;
ruby_init();
return ruby_run_node(ruby_options(myargc, myargv));
}
}
}

0 comments on commit 80df64e

Please sign in to comment.