I ran into a really annoying bug with XCode4 today when I was trying to move my developer profile to another account (for setting up hudson). I had no problems exporting my developer profile from the XCode Organizer, but whenever I tried to import it I got this very strange error message: “Could not locate file within archive”. I tried to google this, but without results.
I noticed that the .developerprofile file was a ZIP archive and unzipped it to inspect what was in it. This is what I found:
Hmm, that unicode stuff there looks suspicous (fun fact, I was named Tobias Rundström before I got married and changed my surname to Hieta). I renamed the file with my name to something more 7-bit friendly and then zipped the file back up with the command
zip -r profile.developerprofile developer
And this solved the problem! If you have this problem and your realname contains some 8-bit characters try to inspect that developerprofile file and see if it helps, certainly did for me!
In the second part of this epic opus about how to make better commits we are going to banish bad whitespaces from commits.
Most people think that I am very picky when it comes to complaining about whitespaces, but there are a couple of valid reasons why you shouldn’t check in a lot of trailing whitespaces. Consider the diff below:
diff --git a/commits.py b/commits.pyindex efa5161..7f99446 100644--- a/commits.py+++ b/commits.py@@ -4,16 +4,23 @@ class Converter:
def csv(self):
returnData = "\n".join([",".join(line) for line in self.source])
- return returnData+ return returnData
def tsv(self):
- returnData = "\n".join(["\t".join(line) for line in self.source])- return returnData+ returnData = "\n".join(["\t".join(line) for line in self.source]) + return returnData ++ def csvSemiColon(self):+ returnData = "\n".join([";".join(line) for line in self.source]) + return returnData + +
if __name__ == "__main__":
a = [["Jonas", "1234567"], ["Anders", "9757272"]]
conv = Converter(a)
print conv.csv()
print conv.tsv()
+ print conv.csvSemiColon()
The lines above contains trailing whitespaces and empty lines, which makes the diff hard to review, because there are changes there that could be hard to spot (what are the difference between the lines where we have invisible characters are removed or added!).
Not only is it hard to review, but it can be hard to merge. If any of the lines above has changed in the repo or branch you are trying to merge with it will create a conflict, even if the SCM normally should be able to solve that.
It should be noted that it’s not only adding whitespaces that can screw up your merge and review, even removing whitespace and empty lines can make it harder to merge and review.
Whitespaces with indentation
Indentation with tabs and whitespaces are also sources of problem with whitespaces. The same problem apply as above, if you change indentation or if you have different methods of indenting between your developers you will get unnecessary merge conflicts and hard to review diffs.
It doesn’t really matter if you are using tabs or spaces to indent your code, the important part is to make sure that all developers are using the same settings.
Remedy
To remedy the problems above there are two things to think about:
Make whitespace and indendentation changes in seperate commits
Configure all editors in the development team to remove whitespaces or at least highlight them so that they are visible and if possible automatically remove them when saved
Another trick that can be very handy is to review the diff in a terminal or text editor before submitting it. A text representation of the diff doesn’t reformat whitespaces to tabs and the other way around.
In large software development teams you can often encounter problems with large commits. How often have a developer been working for weeks on a new feature without commiting even once? How hard was it to merge that? Did anyone manage to review it? If you encounter problems with that big commit, how easy was it to find the problem? This post considers how to make better commits and how to avoid problems like that.
With two words: commit often. With a couple of more words … read on.
Atomic commits
The key is often to do “atomic” commits, meaning commits that are independent from each other. To make it a bit more real, I will use this example program: A simple array to CSV/TSV converter written in Python (ignore the code and language, it’s just an example):
That is the base code we are going to use to show two different examples on how to add features and refactor the code.
We want add support for CSV converter with semi-colon instead of colon. While doing this we realize that we can refactor the code to use list comprehensions instead of the for loop, usually you do all that changes in one honking commit. This is the diff for adding CSV semi-colon and refactor the functions that are already in there:
diff --git a/commits.py b/commits.pyindex 6f1dddb..b07d7ba 100644--- a/commits.py+++ b/commits.py@@ -3,15 +3,15 @@ class Converter:
self.source = source
def csv(self):
- returnData = ""- for line in self.source:- returnData += ",".join(line) + "\n"+ returnData = "\n".join([",".join(line) for line in self.source])
return returnData
def tsv(self):
- returnData = ""- for line in self.source:- returnData += "\t".join(line) + "\n"+ returnData = "\n".join(["\t".join(line) for line in self.source])+ return returnData+ + def csvSemiColon(self):+ returnData = "\n".join([";".join(line) for line in self.source])
return returnData
if __name__ == "__main__":
@@ -19,5 +19,6 @@ if __name__ == "__main__":
conv = Converter(a)
print conv.csv()
print conv.tsv()
+ print conv.csvSemiColon()
That is one messy diff! Hard to see what it actually does, and hard to review, because you have review multiple things at the same time. What we could do instead is to first do the refactoring, commit that and then add the new function, then we get a diff that looks like this for refactoring:
diff --git a/commits.py b/commits.pyindex 6f1dddb..efa5161 100644--- a/commits.py+++ b/commits.py@@ -3,15 +3,11 @@ class Converter:
self.source = source
def csv(self):
- returnData = ""- for line in self.source:- returnData += ",".join(line) + "\n"+ returnData = "\n".join([",".join(line) for line in self.source])
return returnData
def tsv(self):
- returnData = ""- for line in self.source:- returnData += "\t".join(line) + "\n"+ returnData = "\n".join(["\t".join(line) for line in self.source])
return returnData
if __name__ == "__main__":
and this for adding the new feature:
diff --git a/commits.py b/commits.pyindex efa5161..aa276c6 100644--- a/commits.py+++ b/commits.py@@ -9,11 +9,18 @@ class Converter:
def tsv(self):
returnData = "\n".join(["\t".join(line) for line in self.source])
return returnData
++ def csvSemiColon(self):+ returnData = "\n".join([";".join(line) for line in self.source])+ return returnData
if __name__ == "__main__":
a = [["Jonas", "1234567"], ["Anders", "9757272"]]
conv = Converter(a)
print conv.csv()
print conv.tsv()
+ print conv.csvSemiColon()
Much smaller and more focused commits, we see for each function what has been changed and what they have become. In the second commit is very obvious what happened.
A side effect of this is that it’s much easier to write sensible commit messages. Instead of folding two changes and in a commit message that says “Added semi-colon feature” we get two different commit messages that makes sense and describes the full extent of the change. This is good because if something later breaks, it’s much easier to track down the offending commit if the commit message is sensible.
The example above is very small, atomic commits are going to be harder in bigger projects when adding bigger features. A good rule of thumb could be to make sure that each commit can be compiled, executed and tested by itself. That makes it much easier to review and test.
Conclusion
To facilitate code reviews you need to make the commits sane to review. If you keep it atomic, easy to overview and easy to test you get better reviews and less merge problems.
As I mentioned the other day I created some Ubuntu packages for Plex Media Server. Now with the new 0.9.3.4 release they are officially available from the Plex Team!
Features:
Depends on what you need. For i386 it’s only avahi-utils and avahi-daemon, for amd64 they also depend on ia32-libs since there is no native 64bit build yet.
Upstart script. You can start, stop and restart the plexmediaserver with upstart.
/etc/default/plexmediaserver contains configuration of the package. Check the default file for what configuration values can be set.
Automatically creates a plex user that is running the server, which is good for scary security problems.
New updates will come directly from the Plex APT source!
If you have been running PMS before with the old .tar.bz2 package you might need to manually migrate your data to the new paths. Please check my forum post for more information on how to do that.
Telia Digital TV PVR sucks. I just spent ages trying to remove recorded shows from it. There are so many UI annoyances all over the product that they are to many to list, but the remove interface must take the price. This is how you remove shows:
You scroll to the bottom, because you want to remove the oldest entries right?
Click remove, note that you can only remove ONE entry at the time
You confirm that you want to remove this show
You wait for 40-60 seconds while it removes the show
The list scrolls to the top
goto 1
The developers can’t have tested this system on more than a couple of shows. I have over 100 now.
If you haven’t checked out Plex yet, you really should! It’s a great HTPC solution, not only streaming to your machine connected to the TV, but also to mobile devices like iPhone, iPad and Android.
The fine folks over at Plex have released a Linux version of the Plex Media Server (the engine so to speak). It works great with my AppleTV Gen 2, iPhone and iPad (except some subtitle issues that hopefully will be resolved soon). Anyway, they released all this as a nice .tar.gz. Helpful but not really what a APT junkie like I need. So I repackaged their software into a Ubuntu package. You can get my debian scripts on my github page.
I don’t distribute the final .deb for people to use yet, but the Plex Team contacted me (and showed me some nerdy male love), so we might be able to work something out!
Meanwhile, refer to the README in the github page and build away! Please email me if you have any problems.
When it was announced that Snow Leopard would ship with Microsoft Exchange support I was really happy, because I thought that it would mean that I could sync Mail, Contacts and Calendar with Zimbra directly.
That turned out to not be the case. Apple implemented OWA (Outlook Web Access) instead of ActiveSync in Snow Leopard and Zimbra only supports ActiveSync.
But there was hope! Mail was supported via IMAP as it has been for ages and Calendars was supported via CalDAV in iCal. The missing component would be Contacts. For ages Zimbra users on the Mac has been stuck in the Zimbra connector software that syncs Contacts between Zimbra and the AddressBook, unfortunately this software is not very good. The good news was that Snow Leopard would ship with CardDAV support in AddressBook, which would solve this problem!
When Snow Leopard finally shipped the CardDAV support was very broken together with Zimbra. A couple of revisions of SL later and it worked for some people, but not for installations where there where multiple Zimbra domains on the same machine. And it usualy involved a lot of magic in how to enter the URL.
Last week I installed OS X Lion and finally the CardDAV support has been fixed. I have tried it against Zimbra version 6 and it works flawlessly. Happy times!
Configuration is very straight forward. Open up Mail, Contacts and Calendar in System Preferences.
Click the litte Add Account button and select Other
Select CardDAV
And fill in your information.
That’s it! Now you can access your Contacts from Zimbra carefree on your new Shiny OS X Lion machine! Thanks Apple!
note, this is a old archived post, but since it’s linked from some places I ported it over to my new site
Anyone that have tried to email me (or any other email address) on the xmms.org address the last couple of weeks have received a nice error message saying that the address doesn’t exist anymore, what’s up with that? Short answer, the xmms.org domain was sold to a cyber-squatter. To explain how that happened I think we need to go for a quick XMMS history lesson.
XMMS was originally started as X11AMP, it was a clone of the WinAMP player. It later changed it’s name to XMMS (X11 Multi Media System) when someone claimed that they owned the AMP trademark. About the same time a company called 4Front started to sponsor development of XMMS, this effectively put some of the main developers for XMMS on 4Front’s payroll but copyright and license for XMMS was keept intact.
If you don’t remember 4Front it was the company behind OSS (Open Sound System). The idea was to gain PR with XMMS in order to sell more of the commercial OSS licenses. During the dotcom era this seemed to work just fine and everyone was happy.
Over the years XMMS development stagnated to a very slow pace and 4Front didn’t really make that much noise either.
That all changed a couple of weeks ago when the XMMS.org webserver admin received a email from 4Front CEO Dev Mazumdar, stating that he had sold the domain to a company and wanted a full webpage dump. Needless to say, that was pretty surprising! We immediately responded that we where interested in taking over the domain instead, since a lot of us where still actively using it for email and personal webspace. The reply was “We invested a lot of money into XMMS development”, which is an interesting reply on all accounts. Quickly after that the domain was moved and we barely had time to move all our accounts away from the addresses, Dev told us that we should just use xmms.se and xmms2.org instead.
This is where it turns even more strange. In another mail conversation with Dev, he stated that the company buying the domain also wanted to pay 4Front for restarting development of XMMS. Interesting, what company would like to resurrect a very old code base that is mostly replaced by other players these days?
So we decided to have a look into the company that bought the domain to figure out why they would like to buy the domain and restart the development of XMMS. The domain had moved but the contact information for the domain wasn’t changed back then (it is now), but by going directly to the IP address that xmms.org now pointed (200.35.148.194) someone found goftp.com and from there we could extract a list of domains that was embedded in the goftp installer.
www.answermefast.com
www.answermetrue.com
www.965flowers.com
www.answerfever.com
www.accidentadvisors.ca
www.mbquote.ca
www.awesomeanswer.com
www.propertysold.ca
www.extremecow.com
www.askmefast.com
www.goftp.com
www.zinf.org
That list of domains are pretty interesting, note the zinf.org in the end, it’s another open source media player, that has been mostly abandoned as well. It took us a while, but finally we spotted something odd on both goftp.com and zinf.org, linked from the first page there is a new button called “Answers” if you follow it you end up on http://www.zinf.org/qna, I bet the original zinf site didn’t have that on there. So far nothing like this has been added to the xmms.org site, but I guess it’s just a matter of time. Buying these sites just seems to be a way to drive his ad revenue.
Recent digging also shows that the same guy have registered xmms3.org and xmms3.com as well!
It seems like the guy behind all these sites is Doug Collins (which we now can see as the contact info on xmms.org, before that info was available we where able to find his name via the 9and that he goes by the nick doug99 and doug99collins. A quick search on Google shows his dedication to Open Source.
I must say that I don’t really believe that this company will restart development of XMMS or pay any money to 4Front for continue the development. I really hope that Dev lied to us directly about it, otherwise he is pretty dense.
In light of all this some of our community members decided to get a new domain for the old XMMS webpage. So they registered http://www.devmazumdar.com/ in tribute. You can also find the webpage at http://legacy.xmms2.org/
comments on the original post
For postierity I have saved the original comments here
Doug Collins
I do have commercial interests in xmms.org its true. But if I would love to invite the community to use email, do updates, whatever you want. I tried to work with Dev to connect with the community to keep things stable but from the article I now understand that the community was unaware of this shift in ownership. I would love to talk with all of you to re-establish xmms.org. Yes I do want to have an answers section, but the rest of the site can go on as per usual. Email addresses, the web page, etc. I do want to put some $ into developing xmm3 and have been in discussions with Dev as to what that could look like. Resurrecting xmms is definitely in my plans. Anyone have any ideas send them my way. My email is doug99collins [the normal symbol that goes here] gmail.com
PS. I also bought up zinf.org for the same reason. I want to use either or both of these brands to make a new media player that leads the market not follows. I know there are other projects out there but we can re-invent xmms. Well I am rambling but hoping there are those that would like to see xmms revived as well. I would also be happy to see xmms2 content on xmms.org if somebody wants to do that. I am open to suggestions.
Tobias Hieta
Hello Doug
Thanks for taking your time to answer my blog post and thanks for offering email and content hosted on xmms.org. But we are not interested in this, we don’t really like to be associated with your answers section and have no interest in developing any new software together with you or 4Front. My suggestion is that you return xmms.org to us, since we have put a lot of work and effort into the community and the code. We don’t have a registered trademark for XMMS but I think it’s fair to say that we have more invested in the community and software than you have.
If you are not willing to return the xmms.org domain to us, we hope that you can respect our wishes and remove the information about the XMMS player there and just forward that to xmms2.org and legacy.xmms2.org. We will inform our community and the distributions that xmms.org is no longer owned by the community and that we can’t offer any support or guarantees that xmms.org will not contain any harmful code in the future.
Hope you understand that we are not happy about this situation and that we would like to distance ourself from your domain.