Git’ing Aliases Right
In my last post, I talked briefly on how you can manipulate git hooks to do some work for you. So in the past few days I’ve been playing with my pre-commit hook and it’s been working great. However, I’ve made a few changes to it and I found myself manually going through all my repositories to propagate those changes. It dawned on me, why don’t I just store my script in a central place then create a symbolic link within each of the repositories .git/hooks directory.
- In my home directory, I created new sub-directory called
~/.githookswhere I’ve decided that I’m going to store all of my git hooks that should be linked in all of my repositories. - Following the instructions of my previous post, I created a file under
~/.githookscalled pre-commit. - I copied the the contents of the script into my pre-commit file.
- I made sure that
~/.githooks/pre-commitwas executable. - I went to my desired repository and typed the following commands:
$ cd /path/to/repo $ cd .git/hooks $ ln -s ~/.githooks/* .
This is perfect, now I can modify just one script at ~/.githooks instead of having to copy the file to a half-dozen places. However, I was still unsatisfied. I wanted this script to be automatically copied every time I create a new repository. This time I leveraged Git’s Aliases.
Git allows you to come up with your own commands, or aliases. With this in mind, I created a new alias called new. Now instead of running git init to initialize a new git repository, I now can call git new and it will initialize a new repository and create all of my symbolic links for my hooks. This can be done by editing your ~/.gitconfig file and adding a new line under the alias section. If that section does not exist, you can include the following text:
[alias]
new = !git init && ln -s ~/.githooks/* .git/hooks/
Happy git’ing.
No commentsGit’ing Rid of White Space Errors
I’ve been away for a while, but these past two weeks I’ve been re-energized to contribute to the CenterStage UI and Plex development.
During my escapades this evening, I found a really nifty snippet, a Bash one liner for fixing white space errors so Git (and GitHub) stops highlighting in Red, all the code that I’ve introduced with needless white space.
You are supposed to run this one-liner after you’ve added your files to your stagging area using
$ git add
I wanted to take this a step further, not only do I want it to fix my white space errors, I want to do it automatically. That’s where I enlisted the help of Git’s ability to use hooks. Hooks are small scripts that Git executes before or after certain events.
I took the original idea that I borrowed from the Snipplr and created a pre-commit hook that would automatically fix my white space errors before it committed them to the repository.
From the root of my Git repository, I replaced .git/hooks/pre-commit with the following code.
Please note, that you must have execute permissions turned on .git/hooks/pre-commit. You can accomplish this with the following commands:
$ chmod +x .git/hooks/pre-commit
Now every time you commit a text file to your repository, it will make sure the trailing white space errors are removed.
3 commentsStand Under My Umbrella
In my latest adventures I’ve been struggling with a monstrous project (CenterStage) that has a ton of frameworks and interdependencies. Sometimes the interdependencies are too hard to track, should I include this framework or that framework? I can never remember what framework to include. The answer? An umbrella framework.
So I stumbled across an article at Apple’s website. It discusses how binaries are linked against umbrella frameworks and how sub-frameworks must be aware that they are packaged into an umbrella framework. So this is what I did.
- Created my sub frameworks (CSBase, CSUIEngine).
- Created my umbrella framework (CSKit).
- Added a header (CSKit.h) and a source file (so that when it compiles it generates a binary). In the header file I imported the main headers of my sub frameworks.
- In the sub frameworks I added the following linker flag:
OTHER_LDFLAGS = "-sub_framework CSKit" - In the umbrella framework I added the following linker flag:
OTHER_LDFLAGS = "-sub_umbrella CSBase -sub_umbrella CSUIEngine" - In the umbrella framework I added a “Copy Files” build phase and included my sub frameworks.
- In my host application (CenterStage) I linked my application against my umbrella framework (CSKit). I imported
<CSKit/CSKit.h>in my source file.
Instead of adding the linker flags to each project, I created an Xcode Configuration file (.xcconfig). Then I added that configuration file to the sub-framework’s project. If right-click (or double click) on your framework (in the Targets section of Xcode). Under build settings you will find in the lower right hand corner a drop-down box called “Based On.” Click the drop-down box and you will find the configuration file you included in your project. This is an easy way to apply common configurations across multiple projects without hand-jamming it into each project.
Building Regular Expressions into NSString
A quick post today, I stumbled across a post at stiefels.net talking about regular expressions. Cocoa has built-in regular expression engine, it uses ICU’s Specifications.
I ended up using stiefels’ example and implementing it as an NSString extension:
1 2 3 4 5 6 7 8 9 10 | @interface NSString (RegExpExtensions) - (BOOL)doesMatchRegStringExp:(NSString *)string; @end @implementation NSString (RegExpExtensions) - (BOOL)doesMatchRegStringExp:(NSString *)string { NSPredicate *regExpPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", string]; return [regExpPredicate evaluateWithObject:self]; } @end |
Spring Cleaning With Subversion
The most irritating thing in the world is downloading a subversion project that has a bunch of useless files. One or two useless files is fine, but when you have a project with hundreds of these files it gets ridiculous…especially for my slow internet connection. Side note: you think in this day and age we’d all have fiber to our houses — I almost feel like I have dial up sometimes.
Subversion includes a few nifty features to help a project reduce the number of useless files global-ignores and svn:ignore.
Step 1: Global Ignores
First things first, edit your global-ignores. There are files, especially in the Mac, that get created by the operating system (or the build process) that should be ignored across ALL your projects. Such as .DS_Store, object files, and temp files. SVN by default ignores C-style object files (*.o).
There are two places where you can modify the global-ignores. One is the global configurations (applied to the entire computer) the other is the per-user configurations (applied to your user profile). These files are found at /etc/subversion/config and ~/.subversion/config respectively. If they don’t exist create them.
These configuration files use a syntax similar to Windows’ initialization files (see Subversion: Chapter 7. Advanced Topics for more information). There should be at minimum a default file in ~/.subversion/config.
- Open the configuration file and find the section titled
[miscellany]. If it doesn’t exist, create it at the end of the file. - Within that section look for
global-ignores. It may be commented out (line starts with a has character [#]), if it does, just remove the prefixed hash character. If it doesn't exist then create it. - Modify that list, separating each entry with a space. See Example:
[miscellany] ### Set global-ignores to a set of whitespace-delimited globs ### which Subversion will ignore in its 'status' output, and ### while importing or adding files and directories. global-ignores = *.o *.lo *.la #*# .*.rej *.rej .*~ *~ .#* .DS_Store *~.nib *.tmp svn-*.tmp
This is a copy of my configuration file, I globally ignore all temp files and other files that should be generated dynamically by the build process.
Step 2: SVN Properties
You can further manipulate the SVN repository by setting special properties. These properties are specifically applied to a single repository (instead of applying the settings globally). SVN uses svn:ignore to determine a list of files and folders that SVN should ignored. Unlike the configuration file, this list’s entries are separated by carriage returns. The svn:ignore should be set in every folder and subfolder where you wish to ignore build folders or other useless files. The syntax for this command is:
[~/my-great-app]$ svn propset svn:ignore 'list > of > files > or > folders > to > ignore' /path/to/folder
In my repository, I always ignore user-specific configuration files within the Xcode Project folder. Example:
[~/my-great-app]$ svn propset svn:ignore '*.pbxuser > *.mode1 > *.mode1v3' TestProect.xcodeproj/
Note: Make sure you enter a carriage return at the ned of each line.
When coming into a project that is already established, it could be a pain to iterate through all the dependent project folders to set this specific property. Have no fear, find is here!
find has been one of the most powerful commands that I’ve found working with subversion. With find I can easily iterate through all of my repositories’ subfolders and find & manipulate files with only a few lines of code. Revisiting the above example, we can apply this set of svn:ignore properties to all of our Xcode Project folders (*.xcodeproj) within the repository. Example:
[~/my-great-app]$ find . -type d -name '*.xcodeproj' | svn propset svn:ignore '*.pbxuser > *.mode1 > *.mode1v3' [~/my-great-app]$ svn ci -m "Updated the 'svn:ignore' property to exclude *.pbxuser, *.mode1 and *.mode1v3 files."
This example will recurse through the repository beginning in the current folder (.), looking for all objects that match *.xcodeproj pattern (where * is the wild-card), and the object is a directory type (-type d). The list (separated by spaces) is then piped into the svn propset command.
Step 3: Hunt & Destroy
So you’ve set your global ignores and files that the SVN client should ignore when committing files to the repository, but you still have a bunch of these useless files scattered throughout your repository.
Simple! The find command to the rescue:
[~]$ find . -name '.DS_Store' -type f | svn rm [~]$ svn ci -m 'Removed useless files.'1 comment