For a long while we faced an annoying issue with source control binding: we’d load some solution and this would pop up:
We’d then fix it using File/Source control/Change source control/Bind:
And all seemed well – until we loaded the solution again, only to be greeted by the same error message. We’d fix it again, load again, ad infinitum.
Googling around didn’t shed too much light. The p4 binding mechanism isn’t well documented (although where p4 lacks, StackOverflow steps in). Someone described what might be a similar issue, but didn’t get any answers.
- is a text file that holds the actual binding info: the mapping of disk locations to source-control locations. (Note: strictly speaking, the binding info can be encoded inside sln/proj files, but it’s bad practice. The choice of binding location is controlled via a separate file – more in a future post).
When I search my disk for MSSCCPRJ I find dozens (!) of instances scattered throughout my source folders, with contents similar to:
SCC = This is a source code control file
SCC_Project_Name = Perforce Project
SCC_Project_Name = Perforce Project
MSDN lists some specifications the file must adhere too, but leave unspecified its location and scope – that is, the number of projects it describes and their relative-location-on-disk – and here exactly lies a loose end of the p4/VS integration. p4 knowledge base half-admits it:
- Use a Single Solution Model whenever possible. The Single Solution Model uses one .sln file as a container for all of the projects defined by your application
- Use a Consistent Folder Structure for solutions and projects. Ideally, keep solution files in the top directory and all of the projects in subdirectories.
These less-then-precise advice probably mean: avoid a state where a solution includes a project that does not lie below it on disk/source-control. This seems impossible to adhere to in real-life situations (how would you recycle libraries?), and is probably the indirect cause of the MSSCCPRJ mess.
The direct cause is a discrepancy between the disk location where p4 places MSSCCPRJ during project bind, and the disk location where it searches MSSCCPRJ during solution load.
If you bind several projects simultaneously, seems p4 persists the binding info into an MSSCCPRJ at their common ancestor on disk. E.g., if you simultaneously bind D:\code\proj1\proj1.vcxproj, D:\code\proj2\proj2.vcxproj and D:\code\proj3\proj3.vcxproj, the MSSCCPRJ would be generated (or modified) at D:\code. However it seems that during solution load, if p4 uses MSSCCPRJ at D:\code, it would never look for other MSSCCPRJ under D:\code subfolders. So if, for example, some day you bind the single project D:\code\proj4\proj4.vcxproj, an additional MSSCCPRJ would be created at D:\code\proj4, and never be used during solution load, no matter how many times you re-bind the project using the change source control dialog.
The Solution (well, more like a workaround)
Just bind your projects individually. i.e., instead of clicking ‘bind’ on multi-selection:
Repeatedly bind a single selection:
and separate MSSCCPRJ files would be created at every project folder. It can be a hassle for large solutions (I should know – I applied it to ~100 project solutions), but it’s a one-time hassle. For me, that seem to have solved the issue completely.
NOTE: we’re using Perforce 2007.1 and the issue may have been resolved since – although I find that improbable, as the issue seem to persist in the p4 knowledge base. The reason we’re not upgrading is that we’re migrating to TFS instead, and I can’t say I’m too sad about that.