![]() |
|
Spaces home DevelopmentalProfileFriendsBlogMore ![]() | ![]() |
DevelopmentalFlinging crap at other monkeys in the development forest
|
July 01 Rolling back a changeset in TFSIn TFS 2005 and 2008 there is no easy way of rolling back a changeset. Sure, you can do a "get specific version" of each file from before the "bad" checkin occurred, and then check the older version back in. But this really sucks if you have a lot of files in your changeset. Luckily the Team Foundation Power Tools can help you here. One of the command line options is as follows:
Here, you simply replace xxxx with your changeset number, and the power tools will take care of the rest. First, it will "get latest" of the workspace. Next it will perform an operation for each file that is required to roll it back. For example, if you added a file, it performs a delete. If you deleted a file, it performs an undelete. If you simply edited a file, it will get the code from the changeset previous for that file. The result on the command line indicates which changeset was used for each file it rolled back. It then pops up a window requesting confirmation for all the files. After this, it checks out all those files it will roll back and you can then check them in (or only check some in if you so wish). One caveat with this process is that when you are executing the command line, you might get an error: "Unable to determine workspace". This simply means you are not currently in a folder that is part of a workspace. Change directory into a folder that is stored in the workspace you want to use (for those that use multiple workspaces with different folders). Good news is that Rosario will have rollback features incorporated. Check out the help for rollback for more information:
June 13 Destroy Work Item : Is it really gone?This week we had a situation where we needed to remove a work item from the TFS database completely. You can delete a work item in Team Explorer however this just marks the row in the database as deleted and as such your database will always grow, never shrink. The Visual Studio Team System 2008 Team Foundation Power Tools give us the ability to destroy a work item with the 'destroyWI' call. Here's the command line syntax:
The 'intention' is to delete all instances of the ID from the database, and all related data, and in truth it comes pretty close. However there is one table it misses: 'WorkItemsWere' If you look at your TFS database instance you will notice there are actually a few databases. One of them is 'WorkItemTracking' and this database contains all the tables related to work items. The astute might also notice that each of the databases in their instance seems to match each of the web services provided by TFS. Coincidence? In the 'WorkItemTracking' database you will see a number of tables that all contain work item related data. In particular, notice the two tables: 'WorkItemsAre' and 'WorkItemsWere'. The 'Are' table contains the current state of a work item while the 'Were' table contains its history. For example, work item 1234 is modified several times. First it is opened as a bug and assigned to 'triage'. Then triage moves it to the developer who fixes the bug and resolves it with comments, where it is assigned back to the user who opened it. The bug isn't fixed, some additional comments are inserted, its assigned back to the developer, and so on. If you are familiar with work items, you will be able to identify the 'History' section where you can view the audit history. This essentially is what is stored in the 'WorkItemsWere' table. Makes sense now right? Yesterday I did a destroy of a work item and discovered that all the various tables had all instances cleaned up, except the 'WorkItemsWere' table. I contacted the VSTS team who indicated that this is indeed a bug and it is now logged in their own work item system (oh the irony!). What to do in the mean time? Well they assure me it is safe to delete the orphaned database rows, despite the general consensus on the net not to mess with the database directly. I can confirm however that this is the only table with orphaned data. And I'm sure this will be fixed up in a future release of the power tools. All round I quite like the TFPT and haven't even bothered with the multitude of 3rd party components that put a UI in front of it: real men use command line! June 01 Advanced GenericsI've recently been reading this book by Jon Skeet about C# 2 and 3, and it got me all inspired to write about generics. Jon's great; he's extremely active in the C# and Java community, and recently responded to an email question I had in less than 10 minutes! I'm finding the book insightful and useful and greatly enjoying my bus rides to work when I get to read it. This post is going to assume you are familiar with using generic classes like List<T> and Nullable<T>. So lets start with the syntax for declaring our own generic class:
This is pretty simple: the Animator class accepts a generic type T and requires you pass a T in its constructor. The MoveOnce() method is empty at the moment, we'll get to that later.
Great! We've decided that the fact a Monkey can move and stop is pretty general, and is probably something other animals can do, so we've declared an interface to indicate our monkey has those capabilities. We might also define IEater, or IDungFlinger. Now we can revisit our generic type in our Animator class definition as follows:
This is where the magic begins. We've placed a constraint on our generic type, stating that it will only ever accept a type that implements our IMoveable interface. If we try to use the Animator class with something else, we will get a compile-time exception. Even better yet is that our development environment knows that since our instance will always implement IMoveable, it therefore must have a Move() and Stop() method, therefore we can call it anywhere in our class; in this case the MoveOnce() method. You can declare more than one generic type in your class definitions. Imaging a class that facilitates a race for monkeys, whether they be chimps, gorillas, or marmosets. Consider this generic class declaration:
Here we have defined that our class accepts 2 generic types: T and U. We have further restricted them that they both have to inherit from the Monkey class. Here's some example calls using this new class:
As you can see that anything that inherits Monkey is valid. Of interest, the second example shows that even an instance of Monkey is valid. This shows that the where clause in our type restriction means anything that inherits from X or is X. Finally here are a couple of extra cool things you can do with generic type restrictions as general non-monkey related examples:
TestCase1 demonstrates that we can force the type to be a reference type. TestCase3 shows that we can ensure T implements multiple interfaces.
This is valid because Chimp inherits from Monkey. The last TestCase7 is somewhat interesting. Its declaration indicates that T is a reference type, and U is a value type that must inherit from T. How can this be? It essentially states that you must pass a struct that inherits from a class. But C# won't let you declare this. To be honest at first I didn't know the answer to this. Thus the email to Jon, and his explanation was simple and it made sense: interfaces are reference types. Hopefully you are aware that structs can implement interfaces also (but can't do inheritance), so we might define a new animal as follows:
Then we can legitimately use the TestCase7 syntax:
Then of course, valid values for an IMoveable are a Chimp, Marmoset, or even another Mouse, while of course you can only use a Mouse for the second type. Hopefully this has given you a better idea of what you can do with generics. May 29 Contravariance, Covariance, and GenericsThe common question is: what the hell is contravariance and covariance? Ok so you are familiar with casting right? In C# we can do this:
We can also do this:
Because the 'MoveWest' method accepts the narrowing type 'Animal' it is said to support 'Contravariance'. If the C# compiler forced us to only pass exact types, then it would be considered 'invariant'. Likewise C# methods support covariance, in that we can return a narrower type and cast the resulting instance to its correct form. There are parts of the .Net framework however that aren't so flexible. In this case, I'm talking about generics.
Unfortunately this does not compile. We get the following warning:
Why is this? Monkey inherits Animal, so the list conversion is perfectly safe. Well this is one case of invariance. But here's the kicker: word on the street is that the CLR actually supports contravariance of generic lists; its just the C# compiler that doesn't!
Circle Of InterestMy mate and fellow Readifarian Paul Stovell recently posted his 'Circle Of Interest' and started a meme by nominating 5 others to do the same. I was one of the lucky ones, so here's my circle. I don't doubt this circle will change completely in 6 months. I expect the TFS parts to fade into the middle circle, with more focus on WPF and SilverLight perhaps. Who can tell? The big red circle indicates things I don't care about, the baby-vomit yellow indicates stuff I am interest in but have little time or dedication to fully pursue. The dog-vomit green is the stuff that I am loving working or am most eager to develop as soon as possible. Oh, WCF shouldn't be in the middle circle, but I couldn't be bothered changing it. Now, to continue the meme, I nominate these people: Matthew Rowan , John McFadyen , Joseph Cooney , Leon Bambrick Get to it chumps!
|
|
||||||||||||||||||||||||
|
|