I'm very pleased to announce that the wait is over. Today the first official update for SourceSafe 2005 went live on the web. Download away -- it's only 3.5MB.
To quickly bring new readers up to date: this update is a rollup of 64 VSS bug fixes. We focused hard on customer pain points; almost 3/4 of these fixes came directly from people like you filing bugs on Connect and/or calling Customer Support. The result is a variety of improvements to performance, stability, and reliability, plus a few long-time annoyances. In addition, we focused on compatibility with VS 2008 and Vista. I've gone into detail on those topics before so I won't repeat myself.
VS2008
Vista part1 part2
On the other hand, if you've stayed up to date with our VSS releases and are currently running the CTP, there's still plenty here for you.
- full support for all 6 languages (English, Japanese, French, Italian, German, Spanish)
- no manual install step
- 7 extra bug fixes, including some we thought were severe enough to push back this ship date twice :)
My post about VS 2008 and the SourceSafe CTP generated lots of questions. I'll do my best to answer all of them.
Q: Why wasn't this information in the VS2008 README?
A: It should have been. It was definitely in the Orcas Beta1 and Beta2 READMEs. I haven't checked the RTM copy but if it was missing then that's a mistake and I apologize.
Q: Is VSS2005 the official product for VS2008, or is there a VSS2008 around the corner?
A: Yes, VSS 2005 is still the official source control product in the 2008 time frame. (Along with TFS 2008 of course.) There is no VSS 2008. As you've probably noticed, VSS does not ship every time Visual Studio does. For example, VSS 6.0 shipped way back in 1998 with the VB6/VC6 suite of products, and then shipped service packs (6.0c, 6.0d, etc.) with the next few Visual Studio releases. Will there be another major revision of VSS? That's too far away to forecast -- it depends on how the market looks in a few years.
Q: Does SourceSafe 6.0d work with Visual Studio 2008?
A: SourceSafe 6.0d is not officially supported with VS 2008, nor with VS 2005 for that matter. However, it should be possible to get it working if you're willing to accept some limitations. The quickest way is to run "regsvr32 ssscc.dll" from your VSS6\win32 folder.
Q: Where do I get VSS2005 anyway?
A: If you have a Team Edition of Visual Studio 2005 or later, then VSS2005 is included in your license. It was included on the VSTS 2005 set of discs; you can also download it from MSDN. If you have a Professional Edition of Visual Studio or lower then you need to purchase VSS separately.
Q: What's up with all the TLAs?
A: I agree "VSS GDR CTP" is silly. In recent posts here and on the forums, I've taken to calling it simply "the SourceSafe CTP." There's no danger of being ambiguous, because I'm never doing a CTP again ;) -- contrary to Joel's comment, it ended up requiring just as much testing as a real service pack, so there's not much point. Ideally, I'd rather deliver fully-baked updates early and often than wait for another 64 bugs to pile up. Hopefully the DevDiv Hotfix Availability program will keep us moving in the right direction.
As for the final GDR, its official name will be "SourceSafe 2005 Update." Much better. If we do another one, I'd like to see an even simpler naming scheme, such as "SourceSafe 2005b" -> "2005c" -> etc. Internal processes will probably still force us to call them GDRs, but there's no reason to confuse the rest of the world. What do you think?
Just a quick note to let you know that I've updated the list again.
To recap: you can get fixes #1-57 today via the CTP build. English only, I'm afraid. The final GDR ships later this year in all supported languages (English, Japanese, French, Italian, German, Spanish).
You've probably all seen Soma's announcement that the 2008 suite of products officially shipped this morning. Good luck downloading -- our servers are pegged :)
If you plan to use VS 2008 with SourceSafe, make sure to pick up the Update CTP too. Without it, some features like "Open from Source Control" will not work at all. Pay close attention to the install instructions as well. As it says in the KB article:
You may receive error messages when you use Visual Studio 2008. This problem occurs because some compatibility fixes require the Tdnamespaceextension.dll file to be reregistered after you install Visual Studio 2008. To reregister the Tdnamespaceextension.dll file, type the following command at the [elevated - RB] command prompt:
regsvr32 "%programfiles%\Microsoft Visual SourceSafe\tdnamespaceextension.dll"
Sorry about the manual install step. It sucks, I know. The next Update won't have this requirement. (We wanted to ship it before Orcas but ran into some last-minute delays. Expect it before the end of the year.)
Why does SourceSafe need an update anyway? Aren't VS plugin interfaces supposed to be backwards compatible? Yes, they are. In fact, there are no changes to the MSSCCI API in 2008; none of the fixes are related to MSSCCI. (3rd party source control developers can now breathe a sigh of relief). The changes come from the way SourceSafe implements Open from Source Control, Add to Source Control, and Share inside Visual Studio.
Starting in VSS 2005, these functions let you browse the database inside VS's open/add dialogs instead of hanging off the File -> Source Control menu like most other source control providers. It's a cool trick known as a namespace extension. In VS 2008, as you may have noticed, those open/add dialogs got a facelift: like VSS 2005, VS 2008 now uses the standard Windows dialogs. So Vista users in particular get a spiffy new one with integrated search & everything. Unfortunately, that change broke us pretty badly, leading in one way or another to at least 10 of the bugs on my list. Bottom line, you don't want to be caught without the Update linked above.
Hopefully these fixes demonstrate our commitment to keep SourceSafe 2005 a viable option with VS 2008, Vista, and beyond!
All tf.exe commands return one of these:
public enum ExitCode
{
Unknown = -1,
Success = 0,
PartialSuccess = 1,
UnrecognizedCommand = 2,
Failure = 100,
}
You should never see -1. Code 2 is only for the very specific case where you mistype tf someboguscommand <...>. The important exit codes are 0, 1, and 100.
Unfortunately, the definition of PartialSuccess is kind of ambiguous. Like the design decisions around tf.exe's path parameters, different commands ended up with slightly different behavior in v1. For example, if you try to Checkout several files, "partial success" means "at least one edit was successfully pended." Meanwhile, as we'll see, Checkin treats success as all-or-nothing, reserving the PartialSuccess flag for something else. I'm not going to catalog all of these differences, especially since they might be harmonized in the future.* Instead I'm focusing just on tf checkin because:
- It's not intuitive. Yet...
- it's the command whose success or failure is most critical to build scripts & other common automation tasks.
- I already looked up the answers for another customer today :)
As you probably know, Checkin is an all-or-nothing operation. Conflicts, policy failures, etc. on any of involved files will halt the process. This design is part of what allows us to guarantee so-called atomic checkins. As such, we wanted exit code = 0 to unambiguously indicate that a checkin has occurred, with all that implies: new changeset metadata, a new systemwide version number, and so on.
So what in the world does exit code = 1 mean? There are two places in the code where it's set:
- there were no pending changes in your workspace, and you didn't pass any filespec arguments
- all of the pending changes you tried to checkin were silently undone. This in turn means:
- they were all edits
- none of the files had been modified
Situation #1 is pretty straightforward: you used syntax that means "checkin everything", then it turned out there was nothing to do. Situation #2 arises because the server will not let you checkin unmodified files as edits. As a courtesy, TFS removes the edit bit and continues. [This is mildly interesting in the light of the guarantees discussed above. Put simply, we don't consider this a failure. We return 0 so long as at least one file is successfully checked in, no matter how many other files might have been reverted.]
As you can see, both of these situations are closer to "meaningless failure" than "partial success". Was it worth separating them out from exit code = 100 cases? Hopefully :) In any case, you should now have all the info you need to write scripts that incorporate tf checkin commands intelligently.
*Disclaimer: this article merely describes behavior you might find helpful in v1; it does not imply a design contract. Details like this are subject to change in future versions of TFS...though if they did the test team might riot ;-)
When you run Get on a folder (aka project) in VSS Explorer, you're presented with these options:
(if you don't get this dialog, try holding Shift)
Most of the options are obvious, but not "build tree" -- at least not to me. The online help explains it thusly:
Projects only. Overrides the working folders for the subprojects in a recursive operation and builds a project tree on your local computer that mirrors the database project organization. Working folder settings for individual subprojects are ignored. This option is available only when you select the Recursive check box.
Decent explanation -- but if frequent customer inquiries are any guide, it would really benefit from a concrete example. Luckily, Patrick McCormick gave a great one last time the question came up. I've dressed it up with screenshots for added clarity. Let's start with a simple database.
If I run Get on the root ( $/ ), "build tree" will ensure that the file structure created on disk looks the same.
Ordinarily, the "build tree" checkbox is not necessary to get this result. However, it's possible to set explicit working folders in SourceSafe. Working folders might point to completely different locations on disk. If you previously worked with our two WindowsApplications separately it's not likely they map to sibling folders (unless you were very careful). Moreover, if you normally use the Visual Studio IDE, you would never notice because VS uses its own "bindings," not the mappings from VSS Explorer. Thus, you might have inadvertently set up mappings such as
$/WindowsApplication1 -> c:\users\richard\documents\WindowsApplication1
$/WindowsApplication2 -> d:\vss\WindowsApplication2
So long as you're working with these projects independently, that's no big deal. But if you're fetching both of them as part of the same Get operation, there's a good chance you intend to build them together, which means their relative path becomes important. That's the scenario "build tree" intends to enable.
Let's recap Items one more time.
- Items are unique. They have an ID that no other item does.
- Items are versioned. Like all version control systems, TFVC is about making it easy to store successive versions of the same item and retrieve old ones when necessary.
- Items have names. Yes, plural. At a rudimentary level, there's a server path showing where it lives on the server and a local path showing where it lives on your filesystem. More on this later. Suffice to say names are not unique.
- Items have a type. Either they are an ANSI, UTF-16, Binary, etc. file; or they are a directory.
I think #1 and #4 are self-explanatory. We covered #3 in great detail last time. Time to tackle #2. Versions aren't nearly as tricky as names, but there are some historical and terminology issues to cover.
One way to look at the repository is to watch each "slot" over time. ("Slot" is our slang for "server path in committed space.") Every time you checkin a new version of an item, two things happen: a unit of work is recorded, and the new contents of that slot going forward is established.
So far all of this is common to every version control system ever written. In addition, modern version control systems support so-called "atomic checkins." That's actually shorthand for a few related concepts:
- Multiple files can be checked in during the same transaction.
- If any files fail to checkin, the entire operation is aborted.
- Version numbers - or at least some types of version numbers - are consistent across the repository.
- Metadata is associated with the entire collection of files being committed.
Older systems like CVS and SourceSafe didn't have atomic checkins, so a version was a version (or "revision" in CVS terms). Individual items in a modern version control system still have versions, but when we introduced atomic checkins to TFS we needed another word to encapsulate the all the new concepts above. As you probably know, we picked "changeset." Unfortunately, the word doesn't help distinguish between the "two things" (above in boldface) that happen to the repository upon checkin. These two distinct meanings sometimes cause confusion:
- [adj] A point in time. The state of the entire repository immediately after a unit of work was committed. Whenever you specify a "changeset versionspec" in a TFVC command, it takes on this meaning. In this sense changesets are equivalent to dates. (Old posts from Adam and James have more details on versionspecs and date specs in particular.)
- [noun] A unit of work. The files you change during 1 checkin, plus any associated metadata. Whenever you view the contents of a changeset (tf changeset /i, the Changeset dialog, the output of Checkin) you're seeing this meaning. Same for work items: when you link bugs to changesets, you're linking them to that specific unit of work. Unfortunately we don't have an easy way to specify meaning #2 in TFVC commands, except for the 'tfpt getcs' power tool.
That's a lot of words for a really simple distinction. Math terms to the rescue once again. If you think of the repository as a 2D plane like the one pictured above,
meaning #1: all points on a line time = <constant>
meaning #2: a set of revisions that lie on a such a line
By now it should be obvious that a TFVC operation on "changeset versionspec 20" will affect both a.cs and b.cs, while "changeset #20" only contains b.cs. Unfortunately I don't have a special trick for demarcating which meaning of the word I intend, so I'll try to be unambiguous in future discussions of changesets.
Command Line usage
In Source Control Explorer, you're always operating on pending space. At the command line, it's less clear. Consider the following setup: you're working in a directory $/project that's mapped to c:\project and contains two files a.cs and b.cs. For the sake of argument, we'll say they have itemIDs 1 and 2.
c:\project>tf ren b.cs c.cs
c:\project>tf ren a.cs b.cs
c:\project>tf edit $/project/b.cs
Which item gets the edit pended on it? I actually wouldn't know without trying it, because our syntax in TFS v1 is rather haphazard: different tf commands have different rules. Regardless, we can use our new namespace terminology to frame the possible answers. If 'tf edit <serverpath>' operates on pending space, then the answer is item #1. If it operates on committed space, then #2 gets checked out. Ambiguous.
After v1 we tried to clean up this behavior. The new guiding rule is that local paths passed on the command line will be interpreted as pending space, while server paths will be treated as committed space. We feel this is the best compromise between user experience and predictability.
Users usually expect to operate on names as they see them appear on disk. That's pending space: added/branched/undeleted files are present, deleted files are gone, and renames are in effect. You can copy/paste paths from Explorer and it will just work. However, you can't do everything in pending space that you can in committed space. You can't use a pending item as the source of a Branch or Merge; you can't combine a Delete with most other pending changes; and so on. In v1 we allowed such considerations to inspire a plethora of rules like "branch always operates on committed space" that nobody can remember. We were also very forgiving -- for instance, we might allow 'tf <change> $/project/c.cs' or 'tf <change> a.cs' to succeed so long as there was no ambiguity.
Going forward we think it's better to throw an error every now & then if it keeps things more consistent overall. A full review of our APIs with this principle in mind probably won't happen before Rosario, though. Feedback is welcome on this topic!
But wait, there's another wrinkle yet.
Unsynchronized working folder mappings
c:\project>tf workfold $/project/b.cs c:\project\a.cs
c:\project>tf edit a.cs
Which item gets the edit pended on it? Recall that until you run Get, the new mapping does not take effect on disk. That is, a.cs and b.cs are still in their original locations. Yet $/project/b.cs unquestionably maps to a.cs according to our rules, and the server knows this. If we wanted to be pedantic, we'd define another namespace called "unsynchronized local space" to capture the difference between the two viewpoints.
In the end, it comes down to implementation details. When you call Edit, the server looks at the direct item <-> local space mapping that's cached in the LocalVersion table. This is certainly the fastest way to resolve the mapping, and it also happens to coincide with the reality on disk: c:\project\a.cs has item #1's contents at the time you made the call, and item #1 is in fact checked out.
'tf undo' is a special case: we have to perform a Get as part of the operation anyway, so we let you specify either local path.
Clearly, if you combine this quirk with pending renames (or worse, pending parent renames) you could get your brain in quite a twist trying to figure out the correct syntax. In all cases, running Get will clean everything up according to the new mappings.
Case Sensitivity
Our design here is "case-sensitive storage, case-insensitive lookup." Put another way, outputs are case-sensitive while inputs are case-insensitive. To meet that goal, we need these rules:
- You cannot have two items that differ only by case. Sorry Unix folks.
- Thanks to #1, we can let you refer to existing items with the wrong case w/o ambiguity. 'tf edit a.cs' and 'tf edit A.CS' are guaranteed to have the same results.
- Despite #2, we always preserve the case stored on the server unless the Rename bit is set (or Add or Branch, for an item’s very first checkin). Committed space is case-sensitive; the only way to alter it is by checking in a Rename.*
- When we do store a new case-sensitive name (for the first time, or during a rename), we use the name specified during the Add/Branch/Rename, not the one passed to Checkin. In other words, pending space is case-sensitive too. Checkin works exactly like Edit did in #2: its inputs are case-insensitively compared against pending space, yet the output is always the same.
*I think this is the first time I've used the phrase "Rename bit". Internally, we represent the various changetypes as bitflags that can be combined in a surprising # of ways. I'll post the complete chart sometime. Suffice to say that for our purposes, operations like 'tf undelete /newname', or a Merge that brings renames into the target, count because they set the Rename bit.
Edge Cases
- Consider a workspace mapping $/FairlyLongPath -> d:\short. What happens if you create a file under 'short' whose path is MAX_PATH long? The server-side character limit would block your checkin, and the mapping would no longer be surjective! In reality, we don't even let you pend this kind of change. Sorry nitpickers.
- That's not to say you can't break my generalizations; you just have to be more clever. Consider the following set of workspace mappings:
$/a -> c:\a
$/a/b/c -> c:\a\b
At this point your workspace mappings are no longer explicit: the server has to generate an "implicit cloak" for the folder $/a/b.
- If you think hard enough about pending space, you'll realize it's not a transformation directly on committed space. It's really a composition of three functions: committed space => local space => [local] pending space => [server] pending space. The middle function is the one we care about. The 1st and 3rd functions are basically inverses of one another, so we usually ignore them. Likewise, we can work with local paths or server paths in pending space without ambiguity.
However, if you read the preceding section carefully, you'll see they're not perfect inverses. The 1st transform is case-insensitive, while the 3rd is case-sensitive. Consider what happens when you create a workspace mapping with case that differs from committed space:
c:\project>tf workfold $/PROJECT c:\project
c:\project>tf edit A.CS
| Committed | Local | Pending |
| $/project/a.cs | c:\project\a.cs | $/PROJECT/a.cs |
I once wrote to a customer "committed space and pending space should have the same case unless the rename bit is set." As you can see, I was wrong :) It's true that pending the edit using the wrong name 'A.CS' has no effect, as you'd expect from the discussion above. However, because the transform to pending space takes a roundtrip thru your workspace mappings, incorrect case there can bite you. A pending parent rename would also invalidate my statement.
For this customer, the fix was to alter their tool so it used case-insensitive comparisons throughout. That's almost certainly good enough for any & all 3rd-party plugins, thanks to rule #1; if you're programming against TFS, I heartily recommend following suit. Unless your job is actually testing TFS's correctness...
Last time we learned that the principle objects in the source control system are called Items, and a few of their basic properties. That was awhile ago so let's recap:
- Items are unique. They have an ID that no other item does.
- Items are versioned. Like all version control systems, TFVC is about making it easy to store successive versions of the same item and retrieve old ones when necessary.
- Items have names. Yes, plural. At a rudimentary level, there's a server path showing where it lives on the server and a local path showing where it lives on your filesystem. More on this later. Suffice to say names are not unique.
- Items have a type. Either they are an ANSI, UTF-16, Binary, etc. file; or they are a directory.
Today's topic is #3. Names (aka paths) are what users usually see when they interact with Items. Rarely do you know in advance that you want to operate on ItemID #12345. However, since names are not first-class objects in the system, we need a way to translate them back to Items. As it turns out, there are several ways to do this.
Namespaces
We call each consistent class of item names a namespace. The rules for translating a name within a certain namespace to an Item - or to another namespace - we call mappings, aka functions or transformations. It's easiest to describe mappings using terms borrowed from math. Some mappings are injective (aka "one-to-one") or surjective. Sometimes an explicit set of rules defines the mapping; sometimes the mapping is more of a side effect.
Committed space
Committed space is the closest thing we have to a canonical namespace. It's what you see when you browse Source Control Explorer: the server paths of the items checked in to source control. The mapping between items and committed space is one of the fundamental properties we track with each revision, although there is no API to perform the transform explicitly. In addition, the mapping is injective: at any given point in time, each item has exactly one name in committed space. It's not surjective: there are zillions of $/bogus or c:\bogus names that don't map to any item. The only tricky part is variation over time, as users commit renames.
Local space
Local space is where local filesystem paths live. It is defined relative to committed space by workspace mappings, which are explicit and readily exposed to the user. This mapping is surjective: every item in your local workspace maps back to an item in committed space. It is usually not injective, unless you map the entire repository ($/) and don't have any cloaks.
(On the server, there is also a mapping directly from items to each local space. As you might guess it's injective. We won't spend time on it because it's really just an optimization - part of the performance boost you get by tracking local version info - not conceptually important.)
Pending space
Pending space is also a property of a local workspace. It represents the server paths of items as they would look in committed space after you checked in all of your currently pending changes. In other words, it is defined implicitly, by transforming committed space according to any pending renames you have in that workspace. Like local space, this mapping is usually surjective only -- items in pending space map back to committed space, but not vice versa.
We sometimes talk about the pending space of local paths, too. Since the mapping between server & local paths is straightforward, and the idea is the same, it doesn't deserve its own section :)
Target space
Target space is a reflection of committed space from one branch onto another. The Merge operation must generate a mapping between items in the source branch (committed space) and items in the target branch (target space) in order to determine the correct target items to pend changes on. The mapping is implicitly defined by the history of the two branches: any renames that have occurred, whether they were merged, and if so how they were resolved. In the general case the mapping is neither injective nor surjective, because items can be moved in & out of the two branches at will.
Examples
That was all pretty abstract. Let's give an example.
| Changeset | Action |
| 10 | add $/project/branch1/foo/bar.cs |
| 20 | branch it to $/project/branch2/foo/bar.cs |
We now have two items under consideration. Their itemIDs don't really matter except to say that they'll stay the same throughout this exercise. Their names in committed space are trivial: exactly what is shown in the history chart. We'll create a workspace with these mappings:
$/project -> c:\myProj
$/project/branch2 -> c:\myProj2
After we synchronize our workspace to changeset 20, we see clearly that our two items have local names c:\myProj\branch1\foo\bar.cs and c:\myProj2\foo\bar.cs. Edits are the simplest kind of pending change in this context. If we pended an Edit on them, their names in pending space would simply be the same server paths as found in committed space.
| Committed | Local | Pending |
| $/project/branch1/foo/bar.cs | c:\myProj\branch1\foo\bar.cs | $/project/branch1/foo/bar.cs |
| $/project/branch2/foo/bar.cs | c:\myProj2\foo\bar.cs | $/project/branch2/foo/bar.cs |
Pending a namespace operation (Add, Branch, Delete, Undelete, or Rename) is a little more interesting. For example, if we created a 3rd branch, it would have a local path and a server path in pending space (c:\myProj\branch3 and $/project/branch3) but would not exist in committed space. Add and Undelete work similarly; Delete is essentially the reverse. Rename is the most complex, so let's checkin one and pend another:
| 30 | rename $/project/branch1/foo => $/project/branch1/foo-ren |
| 40 | merge branch1 => branch2. Resolve the rename conflict as AcceptYours (aka keep the target name unchanged) |
| [pending] | rename $/project/branch2/foo/bar.cs => $/project/branch2/foo/bar-ren.cs |
At this point, our original two items have the following names:
| Committed | Local | Pending |
| $/project/branch1/foo-ren/bar.cs | c:\myProj\branch1\foo-ren\bar.cs | n/a |
| $/project/branch2/foo/bar.cs | c:\myProj2\foo\bar-ren.cs | $/project/branch2/foo/bar-ren.cs |
A couple things to note. First of all, the downstream affect of recursive operations: our first item has changed names even though it has never been renamed. To answer the question "what was item X's name at time T" it's not enough to look at that item's history. You have to consider the history of its parent folder, grandparent folder, etc. as well as any parent folder it was ever part of. While the changeset that became #30 was still pending, a similar process had to be followed in order to compute its name in pending space.
Second, note that the names of related items have diverged between the two branches. Target space arises because we need to preserve that relationship. To demonstrate, let's checkin our 2nd rename and pend another merge.
| 50 | rename $/project/branch2/foo/bar.cs => $/project/branch2/foo/bar-ren.cs |
| [pending] | merge branch2 => branch1. Resolve the rename conflict as AcceptMerge |
Merge sees that there has been a rename to bar.cs in the source (branch2), and needs to pend the equivalent change in the target (branch1). By looking at the merge history, it determines which target item is related to branch2/foo/bar-ren.cs, i.e. its name in target space. During the first merge, it was straightforward: it just substituted the branch root ($/project/branch2). This time it's more complex:
| Committed | Local | Pending | Target |
| $/project/branch1/foo-ren/bar.cs | c:\myProj\branch1\foo-ren\bar-ren.cs | $/project/branch1/foo-ren/bar-ren.cs | n/a |
| $/project/branch2/foo/bar-ren.cs | c:\myProj2\foo\bar-ren.cs | n/a | $/project/branch1/foo-ren/bar.cs |
Note again that names in target space correspond to names in the other branch's committed space.
One of the changes made between VSS 6.0 and 2005 was to replace ancient file dialogs with common dialogs from the Windows Shell wherever possible. Check out the 6.0 version of Set Working Folder:
It just screams "Win 3.1", complete with floppy diskette icon in the dropdown. By contrast, if you install VSS 2005 on Vista, we can give you a shiny new dialog with no extra work:
There's a secret though: all the old dialogs are still around (in ssgui.dll to be exact). To access them, hold the Shift key as you click the appropriate icon or menu item.
Why should you care? Maybe you have lots of nontechnical users and no training budget. (You devs out there would be surprised how many executive admins, paralegals, HR reps, etc. use VSS to store documents. There was no SharePoint in 1995.) Maybe you rely on UI automation to perform repetitive source control tasks. (As you've probably noticed, not all VSS Explorer functionality is available from the command line and/or IVSS.) Or maybe you're just nostalgic.
Actually, I picked Set Working Folder for a reason. The Windows Browse For Folder dialog has one limitation that the baked-in original did not: you must select a valid folder before the OK button is enabled. Using the old dialog, you can erase the text box and press OK to remove the working folder from your mappings. If you only had the 2005 functionality, you'd be forced to hand-edit the sparsely-documented ss.ini file (yuck).
This post is dedicated to Sara Ford's awesome VS2008 Tip of the Day series.
When I updated Buck's TFS macros for Outlook 2007, I neglected to demonstrate how they were installed. Enough has shifted around in '07 that the question has come up a few times. Let's burn some bandwidth.
1) go to Tools -> Macro -> VB Editor. Doubleclick "ThisOutlookSession" and paste in the code from the previous blog post. Save.
2) bring up a message window. Click the Quick Access Toolbar's dropdown and choose More Commands...
[you could also get here via Glowing Office Button -> Editor Options -> Customize]
3) Choose "Macros" from the dropdown and press the Add button 3X.
4) Hit OK enough times to get back to the main OL screen. Navigate to Tools -> Macro -> Security. Select "no security check for macros." Restart Outlook.
If you don't make this change, your macros will be disabled next time you restart Outlook. (The other option is to digitally sign your macros.)
Disclaimer: turning off macro security is not in any way an official recommendation of Microsoft or the Outlook team. It worked for me and I feel safe about it due to the way I use Outlook and the environment it's in. The Help page for this dialog has a very lucid description of the tradeoffs. Make your own decision.
5) Compose an email. Note the macro icons in the Toolbar. You can now access them via the mouse or keyboard. To view keyboard shortcuts for the Toolbar, as with any Office 2007 ribbon, simply press & release Alt:
The way I have my Toolbar configured, the macros are Alt+4 thru Alt+6.
I've been on vacation the last two weeks, and was silent for several weeks before that. Lots of things from that time stretch I want to share. Most notably, we wrapped up the promised "VSS GDR CTP". Brian Harry was kind enough to announce its RTW in my absence (including an all-too-necessary jab at its TLAs):
Along with the VS2008 wave of products, we are providing an update to Visual SourceSafe 2005 called a GDR. GDR stands for something like General Distribution Release and it is very much like a service pack. The differences are subtle and I won't try to explain them right now. This GDR contains over 57 fixes and includes all customer requested hot fixes and many internally found and fixed issues. It is also designed to make sure that VSS 2005 works well with the VS 2008 wave of products. The update is available for free to all licensed VSS 2005 customers.
We have just released a Community Technology Preview (CTP) for the GDR - ok, the TLAs are getting out of hand now :) You can read about some of the issues it addresses in the following Knowledge Base article: http://support.microsoft.com/kb/939808. And you can download the CTP here if you want to try it out: http://www.microsoft.com/downloads/details.aspx?FamilyID=faf41edd-924d-449f-aefc-9c86dd499720&displaylang=en
The official release of the VSS 2005 GDR will come this fall.
You can find a longer explanation of the terminology and the complete list of bugs among my previous posts. Still, I have quite a blogging backlog from "going dark." First order of business: update said bug list. (edit - done)
I'm a big fan of the work Brian Harry has done to make our processes more transparent. Nevertheless, to badly misquote one of my other bosses, "transparency for the sake of transparency is soo 2006." I chuckled again writing this, because there's a grain of truth there: telling you I produced 4 widgets per furlong yesterday doesn't make your experience with Microsoft dev tools any better.
With that principle in mind, I want to broadcast details about the GDR I just announced. More than that, I want it to be useful. To that end:
- I'm including an ID with each bug. This should allow you to easily refer to bugs among yourselves and when asking us questions. I considered using the internal bug IDs, but
- They would be huge numbers, since it's developed in the same TFS team project as all of Orcas. Huge numbers are meaningless to you, and possibly offensive to the Orcas folks ;-)
- They would be ordered by Creation Date. I want my IDs ordered by Resolved Date so that I can easily append to the list as more bugs are fixed.
- I'm including all bugs regardless of source: DTS bugs, bugs opened on Connect, and bugs opened internally. (DTS bugs are what get created when a case bubbles up from calls to Customer Support. Read Brian's post for more details & caveats.)
- I'm including KB article numbers wherever possible. All DTS bugs that result in a hotfix eventually get a KB article. We may write articles for other bugs too depending on time & interest...no promises though.
| ID | Bug Title | KB article # |
| 1 | DTS:SSuser: SSService.exe fails on Windows 2000 server | 916688 |
| 2 | DTS SSAFE : hotfix request - analyze 2005 -D removes valid items from database | 917491 |
| 3 | DTS : Taking much time (over 30 mins) when checking in 20 M bytes excel file. | |
| 4 | DTS : Failed to open *.pdf files which are registered on Visual SourceSafe 2005 | 925234 |
| 5 | VSS2005: lost internet accounts listed for file security property after web project file merged change from multiple developer | 927004 |
| 6 | Analyze reports corruption on database with root labeled | 923842 |
| 7 | DTS Binary_Mask is not respected during operations like Checkin, Diff, etc result ing corrupting pDF files | 923434 |
| 8 | DTS : Visual SourceSafe 2005 doesn't change the past history contents file format. | 924702 |
| 9 | VSS Merge Changes File Permissions | 927004 |
| 10 | DTS: VSS2005 - Crash on preview of report from History dialog | 925275 |
| 11 | comment template only allow 2 lines | 928392 |
| 12 | DTS: SourceSafe 2005 - Checkin corrupts XML file with diff chain size mismatch error | 927887 |
| 13 | The VSS button in places toolbar doesnt show when running as normal user | |
| 14 | Get Binary file in 2005 results in different file content than retrieving the file in 6.0 (corrupted file) | 930573 |
| 15 | VSS and Vista: The SCC provider is not functioning | |
| 16 | Switching file filters when looking at VSS database causes the DB logging dialog to comeup and doubles all items | |
| 17 | VSS and Vista returning "No such interface supported" when trying to navigate to a VSS database | |
| 18 | VSS namespace extension doesn't respect filter (legacy dialogs only) | |
| 19 | VSS2005 explorer crash when generate report with "include difference" checked at show history dialog | 930573 |
| 20 | Vista: Clicking on ">" and then selecting a VSS item in the drop down list on Vista address bar causes another drop down list to appear | |
| 21 | Add Existing Item dialog should not remember VSS opened paths | |
| 22 | Cannot add multiple files from VSS database | |
| 23 | The VSS full path including user and password are stored in plain string on the MRU list of OS dialogs | |
| 24 | Fix the Orcas+VSS on Vista MRU Issue | |
| 25 | DTS: SourceSafe: Request for QFE to enable Autodetectencoding property set on checked out items | 932058 |
| 26 | DTS Ole automation reports An item with the name "" already exists | 934723 |
| 27 | DTS: Slow performance when checking in large binary file | 932874 |
| 28 | VSS Explorer does not display history or properties on Win2k | |
| 29 | Can't leave file writable during Get Latest | |
| 30 | SS history -#1 -L -B could not ignore blank labels | |
| 31 | Get replaces writable files | |
| 32 | Visual Source Safe Crashes When Right Clicked In TaskBar | |
| 33 | Ole automation get does not retrieve blank folders | |
| 34 | Show Differences report ignores file selection | |
| 35 | Check Out Folder changed to temp directory | |
| 36 | VSS / Visual Studio leaking 22 GDI handles each time Diff window is opened. | |
| 37 | DTS: SSAFE: Timeout errors from Visual Studio accessing VSS 2005 DB over HTTP | 938607 |
| 38 | line command get returns version not found | |
| 39 | DTS: VSS 2005: GET operation from Interface on folder with over 3000 files much slower than in VSS 6.0 | |
| 40 | Visual SourceSafe 2005 crashes when right clicking in the taskbar | |
| 41 | Canceling a large get operation results in files being left writable | |
| 42 | Label promotion after "share, pin, and branch" operation fails when retrieve at subfolder level | |
| 43 | DTS Recursive diff does not follow assign working directories | |
| 44 | DTS: VSS 2005 Is there a way to disable auto detect file type when dragging and dropping files in VSS Explorer | |
| 45 | DTS: "File or project not found" retrieving VSSVersion.VSSItem on rollback items | |
| 46 | VSS:An unexpected error dialog appears before log-on to VSS database dialog while opening a project from VSS. | |
| 47 | Source Safe item in Places Toolbar has a generic name inconsistent with the Whidbey scheme | |
| 48 | SCCI: Changing destination folder during OpenFromScc is broken if you have Whidbey VSS + Orcas VS installed | |
| 49 | Open Project Dialogs' "Error Renaming Database" alert is not modal | |
| 50 | SCCI RAP: Closing VS causes a crash when open an exsiting solution to different destination folder from SCC(Remote) | |
| 51 | AddItemProjectFromVSS does not work | |
| 52 | Many error alerts appear when opening solution from SCC using VSS Internet (RAP) | |
| 53 | Messages do not show in output for source control | |
| 54 | Cannot connect to VSS over HTTP when using Vista + Whidbey SP1 + VSS Admin | |
| 55 | Archive Pinned File Reverts to wrong version | |
| 56 | DTS : VSS2005 Analyz.exe throw C++ EH exception. | |
| 57 | VSS Explorer launches visual merge when there are no conflicts | |
| 58 | Changing the 'Store only latest version' property should require the Destroy permission | |
| 59 | SCC/VSS: SCC Plug-in Settings for "Login ID" is not being retained/used properly... | |
| 60 | Visual SourceSafe 2005/6.0d: Can add file with "%" in filename, but can't check-in changes. | |
| 61 | VSS: it says "path does not exist" while opening file from SCC to a valid path after uninstalling Whidbey | |
| 62 | Source Safe Custom Editor configuration is case sensitive | |
| 63 | SCCI RAP: Failed to add web project into vss server when web page is open to design view | |
| 64 | Open project from SCC fails with VSS SP1 when running VS as administrator | |
In case you're wondering, there is a pretty even mix between the sources of bugs that I mentioned above. To be exact:
-
DTS: 22
-
Other CSS customers: 6
-
Connect: 11
-
Internal testing: 16
(charts and statistics are as of 6/6/2007 - I will update this)
"Other customers" are bugs that were reported to Customer Support Services but opened outside the DTS process, either because the issue was not severe enough or the customer didn't want to pursue a hotfix. So in sum, 39/55 or 71% of the bugs we are fixing come directly from you. Keep'm coming!
update 8/6/2007: added #56-57. I'm not going to recalc the statistics.
update 11/16/2007: added #58-63. No stats recalc. These will be in the final release only, not the CTP we shipped in July.
When I upgraded to OL2007, Buck's great little macros stopped working. Today, I finally got the guts to ask the Outlook guys what they broke improved. The answer was simple enough. I'll let the code do the talking:
Sub LinkToWorkItem()
Set oDoc = ActiveInspector.WordEditor
Set oWord = oDoc.Application
Set oSelection = oWord.Selection
'' Convert the current selection to a work item hyperlink'
oDoc.Hyperlinks.Add Anchor:=oSelection.Range, Address:= _
"http://tfserver:8080/WorkItemTracking/Workitem.aspx?artifactMoniker=" _
& oSelection.Text, _
SubAddress:="", ScreenTip:="", TextToDisplay:=oSelection.Text
End Sub
Sub LinkToKB()
Set oDoc = ActiveInspector.WordEditor
Set oWord = oDoc.Application
Set oSelection = oWord.Selection
'' Convert the current selection to a KB article hyperlink'
oDoc.Hyperlinks.Add Anchor:=oSelection.Range, Address:= _
"http://support.microsoft.com/kb/" _
& oSelection.Text, _
SubAddress:="", ScreenTip:="", TextToDisplay:=oSelection.Text
End Sub
Sub LinkToChangeset()
Set oDoc = ActiveInspector.WordEditor
Set oWord = oDoc.Application
Set oSelection = oWord.Selection
'' Convert the current selection to a changeset hyperlink'
oDoc.Hyperlinks.Add Anchor:=oSelection.Range, Address:= _
"http://tfserver:8080/VersionControl/VersionControl/Changeset.aspx?artifactMoniker=" _
& oSelection.Text, _
SubAddress:="", ScreenTip:="", TextToDisplay:=oSelection.Text
End Sub
LinkToKB() technically doesn't have anything to do with TFS, but I went ahead and added it while I was playing with Outlook macros.
In the next post, you'll see why...
We finally have a name. Last time I blogged about the future of SourceSafe, I had to constantly refer to "the next servicing release." No more. That next release will officially be a "GDR" -- and it's coming sooner than you think.
Some brief history on Developer Division nomenclature. Hotfixes are one-off solutions to a specific problem: they are tested briefly, then given directly to customers. A knowledge base article is written to document their existence, but the hotfix itself is not posted publicly; customers must call support to receive them. They are not normally cumulative. (We make VSS hotfixes cumulative since redeploying the whole product only takes about about 4MB. Wouldn't work for Visual Studio, obviously.) Service packs contain a large number of fixes. They are tested very thoroughly by the entire QA organization across our entire matrix of configurations; they receive a full security review; they are localized into every language we support; and so on. SPs are posted on the main MS download page where anyone can get them instantly. They are always cumulative.
A GDR is somewhere in between. They typically contain one large fix, or several related fixes, and receive a moderate amount of testing. As it turns out, our GDR will contain a lot of fixes -- more than some SPs. I hope to share the list with you shortly. It will probably be posted on Connect: anyone can download it, but they must first register with the website (via Passport) so that downloads can be tracked. We're also investigating whether we can leverage Microsoft Update for broader visibility.
Given that background, I'm happy to report that the DevDiv release team accepted our bid to distribute in GDR form. Sorry to add yet another TLA to your vocabulary. On the bright side, what this means is that we can deliver a very broad range of fixes to you without much of the overhead that accompanies a SP. (Those of you who waited...and waited...for Whidbey SP1 know what I mean.) We don't have the resources to commit that kind of effort to SourceSafe.
At the same time, we do want to continue raising the quality of the product. It will be tested across five core languages: Japanese, French, Italian, German, and Spanish. It will be supported on all platforms, including Vista and Orcas, giving a high priority to compatibility issues. Best of all, it will be released early and often for your feedback, as promised. The volunteer testing program described therein is already underway. If all goes well, we'll release a CTP in just a few weeks! (English only) As for the final release, I'm going to keep the goalposts at "later this year" for now :)