Permalink
Browse files

Merge branch 'feature'

Conflicts:
	ext/extconf.rb
  • Loading branch information...
2 parents e50b423 + 877b466 commit b1d296ef6de80b1d7f0aecb4ee5c8a79b5d2bdf4 @ttilley ttilley committed Jan 29, 2012
View
@@ -10,7 +10,8 @@ Gemfile.lock
.fseventsd
Desktop DB
Desktop DF
-/bin/fsevent_watch
+
+# /bin/fsevent_watch
/ext/Makefile
## editor/IDE
View
@@ -4,8 +4,9 @@ Very simple & usable Mac OSX FSEvents API
- RubyCocoa not required!
- Signals are working (really)
-- Tested on MRI 1.8.7 & 1.9.2
-- Tested on JRuby 1.6.3
+- Tested on MRI 1.8.7 & 1.9.2, JRuby 1.6.3
+- Tested on 10.6 & 10.7 (though 10.5 should work just as well)
+- Tested with XCode 3.2.6, 4.0.2, 4.1, 4.2b5
== Install
View
Binary file not shown.
View
@@ -1,64 +0,0 @@
-# Workaround to make Rubygems believe it builds a native gem
-require 'mkmf'
-create_makefile('none')
-
-# TODO: determine whether we really need to be working around instead of with mkmf
-
-if `uname -s`.chomp != 'Darwin'
- puts "Warning! Only Darwin (Mac OS X) systems are supported, nothing will be compiled"
-else
- begin
- xcode_path = %x[xcode-select -print-path].to_s.strip!
- rescue Errno::ENOENT
- end
-
- raise "Could not find a suitable Xcode installation" unless xcode_path
-
- gem_root = File.expand_path(File.join('..'))
- darwin_version = `uname -r`.to_i
- sdk_version = { 9 => '10.5', 10 => '10.6', 11 => '10.7' }[darwin_version]
-
- raise "Only Darwin systems greater than 8 (Mac OS X 10.5+) are supported" unless sdk_version
-
- core_flags = %W{
- -isysroot "#{xcode_path}/SDKs/MacOSX#{sdk_version}.sdk"
- -mmacosx-version-min=#{sdk_version} -mdynamic-no-pic -std=gnu99
- }
-
- cflags = core_flags + %w{-Os -pipe}
-
- arch_sig = `uname -m`
- cflags << '-arch i386' if arch_sig =~ /i386$/i
-
- wflags = %w{
- -Wmissing-prototypes -Wreturn-type -Wmissing-braces -Wparentheses -Wswitch
- -Wunused-function -Wunused-label -Wunused-parameter -Wunused-variable
- -Wunused-value -Wuninitialized -Wunknown-pragmas -Wshadow
- -Wfour-char-constants -Wsign-compare -Wnewline-eof -Wconversion
- -Wshorten-64-to-32 -Wglobal-constructors -pedantic
- }
-
- ldflags = %w{
- -dead_strip -framework CoreServices
- }
-
- cc_opts = core_flags + ldflags
-
- cc_opts += %w{
- -D DEBUG=true
- } if ENV['FWDEBUG'] == "true"
-
- cc_bin = `which clang || which gcc`.to_s.strip!
-
- compile_command = "CFLAGS='#{cflags.join(' ')} #{wflags.join(' ')}' #{cc_bin} #{cc_opts.join(' ')} -o '#{gem_root}/bin/fsevent_watch' fsevent/fsevent_watch.c"
-
- STDERR.puts(compile_command)
-
- # Compile the actual fsevent_watch binary
- system "mkdir -p #{File.join(gem_root, 'bin')}"
- system compile_command
-
- unless File.executable?("#{gem_root}/bin/fsevent_watch")
- raise "Compilation of fsevent_watch failed (see README)"
- end
-end
View
@@ -1,226 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <CoreServices/CoreServices.h>
-
-
-// Structure for storing metadata parsed from the commandline
-static struct {
- FSEventStreamEventId sinceWhen;
- CFTimeInterval latency;
- FSEventStreamCreateFlags flags;
- CFMutableArrayRef paths;
-} config = {
- (UInt64) kFSEventStreamEventIdSinceNow,
- (double) 0.3,
- (UInt32) kFSEventStreamCreateFlagNone,
- NULL
-};
-
-// Prototypes
-static void append_path(const char *path);
-static inline void parse_cli_settings(int argc, const char *argv[]);
-static void callback(FSEventStreamRef streamRef,
- void *clientCallBackInfo,
- size_t numEvents,
- void *eventPaths,
- const FSEventStreamEventFlags eventFlags[],
- const FSEventStreamEventId eventIds[]);
-
-
-// Resolve a path and append it to the CLI settings structure
-// The FSEvents API will, internally, resolve paths using a similar scheme.
-// Performing this ahead of time makes things less confusing, IMHO.
-static void append_path(const char *path)
-{
-#ifdef DEBUG
- fprintf(stderr, "\n");
- fprintf(stderr, "append_path called for: %s\n", path);
-#endif
-
- char fullPath[PATH_MAX];
-
- if (realpath(path, fullPath) == NULL) {
-#ifdef DEBUG
- fprintf(stderr, " realpath not directly resolvable from path\n");
-#endif
-
- if (path[0] != '/') {
-#ifdef DEBUG
- fprintf(stderr, " passed path is not absolute\n");
-#endif
- size_t len;
- getcwd(fullPath, sizeof(fullPath));
-#ifdef DEBUG
- fprintf(stderr, " result of getcwd: %s\n", fullPath);
-#endif
- len = strlen(fullPath);
- fullPath[len] = '/';
- strlcpy(&fullPath[len + 1], path, sizeof(fullPath) - (len + 1));
- } else {
-#ifdef DEBUG
- fprintf(stderr, " assuming path does not YET exist\n");
-#endif
- strlcpy(fullPath, path, sizeof(fullPath));
- }
- }
-
-#ifdef DEBUG
- fprintf(stderr, " resolved path to: %s\n", fullPath);
- fprintf(stderr, "\n");
- fflush(stderr);
-#endif
-
- CFStringRef pathRef = CFStringCreateWithCString(kCFAllocatorDefault,
- fullPath,
- kCFStringEncodingUTF8);
- CFArrayAppendValue(config.paths, pathRef);
- CFRelease(pathRef);
-}
-
-// Parse commandline settings
-static inline void parse_cli_settings(int argc, const char *argv[])
-{
- config.paths = CFArrayCreateMutable(NULL,
- (CFIndex)0,
- &kCFTypeArrayCallBacks);
-
- for (int i = 1; i < argc; i++) {
- if (strcmp(argv[i], "--since-when") == 0) {
- config.sinceWhen = strtoull(argv[++i], NULL, 0);
- } else if (strcmp(argv[i], "--latency") == 0) {
- config.latency = strtod(argv[++i], NULL);
- } else if (strcmp(argv[i], "--no-defer") == 0) {
- config.flags |= kFSEventStreamCreateFlagNoDefer;
- } else if (strcmp(argv[i], "--watch-root") == 0) {
- config.flags |= kFSEventStreamCreateFlagWatchRoot;
- } else if (strcmp(argv[i], "--ignore-self") == 0) {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
- config.flags |= kFSEventStreamCreateFlagIgnoreSelf;
-#else
- fprintf(stderr, "MacOSX10.6.sdk is required for --ignore-self\n");
-#endif
- } else {
- append_path(argv[i]);
- }
- }
-
- if (CFArrayGetCount(config.paths) == 0) {
- append_path(".");
- }
-
-#ifdef DEBUG
- fprintf(stderr, "config.sinceWhen %llu\n", config.sinceWhen);
- fprintf(stderr, "config.latency %f\n", config.latency);
- fprintf(stderr, "config.flags %#.8x\n", config.flags);
- fprintf(stderr, "config.paths\n");
-
- long numpaths = CFArrayGetCount(config.paths);
-
- for (long i = 0; i < numpaths; i++) {
- char path[PATH_MAX];
- CFStringGetCString(CFArrayGetValueAtIndex(config.paths, i),
- path,
- PATH_MAX,
- kCFStringEncodingUTF8);
- fprintf(stderr, " %s\n", path);
- }
-
- fprintf(stderr, "\n");
- fflush(stderr);
-#endif
-}
-
-static void callback(FSEventStreamRef streamRef,
- void *clientCallBackInfo,
- size_t numEvents,
- void *eventPaths,
- const FSEventStreamEventFlags eventFlags[],
- const FSEventStreamEventId eventIds[])
-{
- char **paths = eventPaths;
-
-#ifdef DEBUG
- fprintf(stderr, "\n");
- fprintf(stderr, "FSEventStreamCallback fired!\n");
- fprintf(stderr, " numEvents: %lu\n", numEvents);
-
- for (size_t i = 0; i < numEvents; i++) {
- fprintf(stderr, " event path: %s\n", paths[i]);
- fprintf(stderr, " event flags: %#.8x\n", eventFlags[i]);
- fprintf(stderr, " event ID: %llu\n", eventIds[i]);
- }
-
- fprintf(stderr, "\n");
- fflush(stderr);
-#endif
-
- for (size_t i = 0; i < numEvents; i++) {
- fprintf(stdout, "%s", paths[i]);
- fprintf(stdout, ":");
- }
-
- fprintf(stdout, "\n");
- fflush(stdout);
-}
-
-int main(int argc, const char *argv[])
-{
- /*
- * a subprocess will initially inherit the process group of its parent. the
- * process group may have a control terminal associated with it, which would
- * be the first tty device opened by the group leader. typically the group
- * leader is your shell and the control terminal is your login device. a
- * subset of signals triggered on the control terminal are sent to all members
- * of the process group, in large part to facilitate sane and consistent
- * cleanup (ex: control terminal was closed).
- *
- * so why the overly descriptive lecture style comment?
- * 1. SIGINT and SIGQUIT are among the signals with this behavior
- * 2. a number of applications gank the above for their own use
- * 3. ruby's insanely useful "guard" is one of these applications
- * 4. despite having some level of understanding of POSIX signals and a few
- * of the scenarios that might cause problems, i learned this one only
- * after reading ruby 1.9's process.c
- * 5. if left completely undocumented, even slightly obscure bugfixes
- * may be removed as cruft by a future maintainer
- *
- * hindsight is 20/20 addition: if you're single-threaded and blocking on IO
- * with a subprocess, then handlers for deferrable signals might not get run
- * when you expect them to. In the case of Ruby 1.8, that means making use of
- * IO::select, which will preserve correct signal handling behavior.
- */
- if (setpgid(0,0) < 0) {
- fprintf(stderr, "Unable to set new process group.\n");
- return 1;
- }
-
- parse_cli_settings(argc, argv);
-
- FSEventStreamContext context = {0, NULL, NULL, NULL, NULL};
- FSEventStreamRef stream;
- stream = FSEventStreamCreate(kCFAllocatorDefault,
- (FSEventStreamCallback)&callback,
- &context,
- config.paths,
- config.sinceWhen,
- config.latency,
- config.flags);
-
-#ifdef DEBUG
- FSEventStreamShow(stream);
- fprintf(stderr, "\n");
- fflush(stderr);
-#endif
-
- FSEventStreamScheduleWithRunLoop(stream,
- CFRunLoopGetCurrent(),
- kCFRunLoopDefaultMode);
- FSEventStreamStart(stream);
- CFRunLoopRun();
- FSEventStreamFlushSync(stream);
- FSEventStreamStop(stream);
-
- return 0;
-}
@@ -0,0 +1,23 @@
+# xcode
+build/*
+*.pbxuser
+!default.pbxuser
+*.mode1v3
+!default.mode1v3
+*.mode2v3
+!default.mode2v3
+*.perspectivev3
+!default.perspectivev3
+*.xcworkspace
+!default.xcworkspace
+xcuserdata
+profile
+*.moved-aside
+
+# macos
+.DS_Store
+Icon?
+._*
+.Spotlight-V100
+.Trashes
+
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleIdentifier</key>
+ <string>com.teaspoonofinsanity.fsevent_watch</string>
+ <key>CFBundleExecutable</key>
+ <string>fsevent_watch</string>
+ <key>CFBundleName</key>
+ <string>fsevent_watch</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>MACOSX_DEPLOYMENT_TARGET</string>
+ <key>CFBundleVersion</key>
+ <string>CURRENT_PROJECT_VERSION</string>
+ <key>FSEWOptimizationLevel</key>
+ <string>OPTIMIZATION_LEVEL</string>
+ <key>FSEWVersionInfoBuilder</key>
+ <string>VERSION_INFO_BUILDER</string>
+ <key>FSEWVersionInfoString</key>
+ <string>VERSION_INFO_STRING</string>
+ <key>BuildMachineOSBuild</key>
+ <string>MAC_OS_X_PRODUCT_BUILD_VERSION</string>
+ <key>BuildMachineOSVersion</key>
+ <string>MAC_OS_X_VERSION_ACTUAL</string>
+ <key>DTCompiler</key>
+ <string>GCC_VERSION</string>
+ <key>DTPlatformBuild</key>
+ <string>PLATFORM_PRODUCT_BUILD_VERSION</string>
+ <key>DTSDKBuild</key>
+ <string>SDK_PRODUCT_BUILD_VERSION</string>
+ <key>DTSDKName</key>
+ <string>SDK_NAME</string>
+ <key>DTXcode</key>
+ <string>XCODE_VERSION_ACTUAL</string>
+ <key>DTXcodeBuild</key>
+ <string>XCODE_PRODUCT_BUILD_VERSION</string>
+</dict>
+</plist>
View
@@ -0,0 +1,21 @@
+Copyright (c) 2011 Travis Tilley
+
+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.
+
Oops, something went wrong.

0 comments on commit b1d296e

Please sign in to comment.