Showing posts with label geek. Show all posts
Showing posts with label geek. Show all posts

Tuesday, May 18, 2010

[unix geeky] ignoring files at svn add time

Executive summary for the impatient: add everything, then svn revert [-R] what you don't want, then set up svn:ignore properties as per usual.

Random thing that I figured out, after having some unsuccessful google searches. Here's hoping this little tidbit will save someone some time some day.

For those using Subversion and Xcode, this may be particularly relevant. And that'll be my example, though I'm sure there are plenty of other times that this could come up, as well.

When creating a new project (let's call it "Foo") in Xcode, a bunch of stuff is created. for example, when I create a new iPhone application project called Foo, I get the following hierarchy of files:

Foo/Classes/
Foo/Classes/FooAppDelegate.h
Foo/Classes/FooAppDelegate.m
Foo/Foo-Info.plist
Foo/Foo-Info.plist.orig
Foo/Foo.xcodeproj/
Foo/Foo.xcodeproj/TemplateInfo.plist.orig
Foo/Foo.xcodeproj/lindes.mode1v3
Foo/Foo.xcodeproj/lindes.pbxuser
Foo/Foo.xcodeproj/project.pbxproj
Foo/Foo_Prefix.pch
Foo/MainWindow.xib
Foo/build/
Foo/build/Foo.build/
Foo/build/Foo.build/Foo.pbxindex/
Foo/build/Foo.build/Foo.pbxindex/categories.pbxbtree
Foo/build/Foo.build/Foo.pbxindex/cdecls.pbxbtree
Foo/build/Foo.build/Foo.pbxindex/decls.pbxbtree
Foo/build/Foo.build/Foo.pbxindex/files.pbxbtree
Foo/build/Foo.build/Foo.pbxindex/imports.pbxbtree
Foo/build/Foo.build/Foo.pbxindex/pbxindex.header
Foo/build/Foo.build/Foo.pbxindex/protocols.pbxbtree
Foo/build/Foo.build/Foo.pbxindex/refs.pbxbtree
Foo/build/Foo.build/Foo.pbxindex/strings.pbxstrings/
Foo/build/Foo.build/Foo.pbxindex/strings.pbxstrings/control
Foo/build/Foo.build/Foo.pbxindex/strings.pbxstrings/strings
Foo/build/Foo.build/Foo.pbxindex/subclasses.pbxbtree
Foo/build/Foo.build/Foo.pbxindex/symbols0.pbxsymbols
Foo/main.m


Of these, there are a few things I don't want:
  1. The entire Foo/build/ hierarchy.
  2. the lindes.pbxuser and lindes.mode1v3 files under Foo/Foo.xcodeproj. (I'm actually not 100% sure there's no useful information in these files, but they sure do change a lot, and I think most of the important stuff is in project.pbxproj, so... here's hoping these are safe to ignore. If anyone knows more about that, please feel free to point me at an authoritative reference or give me the skinny in the comments.)

If I do just svn add Foo, though, I get those things. I want to ignore them.

Well, I can do svn propset svn:ignore build Foo after my add, but build has already been added, so it's still going to go into the repository if I don't do something about it. (And then I'd do the same thing (but most likely using svn propedit) for *.pbxuser and *.mode1v3 under the xcodeproj directory.)

So what I was looking for was an option for telling svn add to ignore certain things during the add process. As far as I was able to determine, there is no option to svn add that will do this. But there is a way to get basically what I want! It's called "svn revert". With appropriate options, it will make svn forget you ever added something, without otherwise modifying anything.

Here's an example set of commands that would do the trick:

: $; svn add Foo
: $; cd Foo
: $; svn revert -R build
: $; svn propset svn:ignore build .
: $; cd Foo.xcodeproj
: $; svn revert *.pbxuser *.mode1v3
: $; svn propset svn:ignore "*.pbxuser
*.mode1v3" .

: $; cd ..
: $; svn status


(Couple quick notes: (1) my shell prompt is ': $; ' (and the text actually typed is in bold), (2) in that second svn propset, I actually hit return inside the quotes. In my shell (zsh), I get a second-level prompt of 'dquote> ' when I do this, but I didn't want to confuse the text above with that.)

And that does the trick. If I now do an svn status, I get:

A .
A Foo.xcodeproj
A Foo.xcodeproj/TemplateInfo.plist.orig
A Foo.xcodeproj/project.pbxproj
A main.m
A Foo-Info.plist.orig
A Foo-Info.plist
A Foo_Prefix.pch
A Classes
A Classes/FooAppDelegate.h
A Classes/FooAppDelegate.m
A MainWindow.xib


No "?" lines, no build or its contents, and no pbxuser or mode1v3 files. Perfect!

(Well, OK, it might be useful to do something with TemplateInfo.plist.orig, but... that's something to figure out another day. :-)

Thursday, March 13, 2008

[unix-geeky] : My UNIX shell prompt $;

It occurs to me that this blog could be, among other things, a place to share random unix tips and tricks that I've picked up over the years. Non-geek types are encouraged to go find a photography-related post or something. ;-) For the geek types still reading, here's a little something:

When choosing your prompt for any Bourne Shell derivative (sh, ksh, bash, zsh, and probably others I don't know about -- zsh is my current shell of choice, by the way), I find it handy to have my prompt follow this simple set of rules:
  1. the first character is a colon
  2. the second character is a space
  3. The last non-space character is a semicolon
  4. No other semicolons in the line (unless they're immediately followed by another colon and space)

Using the traditional "$" as a starting point, I might then put something like the following in my .profile (or .bash_profile or .zshrc or what have you -- .profile is the traditional Bourne shell location, so that's what I list):

PS1=": $; "

And thus a bit of my shell session might look like:

: $; 
: $;
: $; date
Thu Mar 13 19:01:28 PDT 2008
: $; pwd
/home/lindes/tmp/sh-demo
: $; ls -CAF
.profile
: $; cat .profile
# this is a fake .profile file
# it would normally have a lot of content. For now, just this:
PS1=": $; "
export PS1 # possibly redundant
: $;
: $;
: $; : $; date
Thu Mar 13 19:04:13 PDT 2008
: $;

Now, why is this useful? And why does my prompt show up twice before that second call to the date command?

Well, as seasoned readers may already have guessed, there's some magic in this prompt. In Bourne-derived shells (as listed above), ':' is a shell-builtin command which does nothing more than have zero* as its exit status. Same deal as /bin/true, but in a single character command. And guess what? It takes arguments, and happily ignores them all. And as hopefully most of you (if you've bothered to read this far) already know, a semicolon separates commands. So that second time I ran date above, I did not get a double prompt from my shell, and I did not type my prompt in. No, instead what I did was a copy and pasted that command-line from earlier, by copying the whole line -- including the prompt. And it still worked, and didn't give me anything extraneous.

How cool is that?

Normally, I couldn't copy the whole line and still get desired behavior:
: $; PS1='$ '
$ date
Thu Mar 13 19:16:17 PDT 2008
$ $ date
zsh: command not found: $
$

(And it could be much worse than that, depending on what else is in your prompt.)

Starting with a colon and a space, and ending with a semicolon (and, for clarity only, another space), I can copy and paste the whole line.

My normal prompt is a lot longer than just : $; , and includes a bunch of different information that I find useful. Perhaps someday I'll write a blog entry about that. For now, just know that it always starts with a colon and a space, and ends with a semicolon (and a space). And whenever I write documentation which needs to include a shell prompt, the prompt shown will probably always be : $; (or maybe : #; , though that actually has problems of its own. Extra special feel-good (that's all you get) bonus points for those who can say why.)


Happy geeking!



Footnotes:

*: Check it out:
: $; grep '\<0\>' /usr/include/sysexits.h
#define EX_OK 0 /* successful termination */

Thus, zero means successful exit.