Mercurial repository & MSVS - two projects & shared files - visual-studio-2010

I am currently developping an application in MS VS2010 that's based on a client-server architecture with one project for each part in VS. Until recently, they both had their own repositories in Hg, but I decided to move them together as there are quite a few files that are now shared.
I have been using hard links to make sure that the changes on one file are propagated to the same file in the other folder/project. However, if you clone the repository or check out from the online repository, the hard links are broken.
I have read up as much as I could on both soft & hard links with Hg, and neither of them seems to be a good, portable solution at this point. What method of sharing the files between the two projects would you recommend, keeping in mind that I would ideally like a clean structure that is also reflected in VS?
Best regards,
Max.

You could use Mercurial's sub-repository feature to put your shared files in an external repository and share it in the places you need. There's also the guest repository extension, which is relatively newer and lighter-weight than a sub-repo.
Instead of solving it in version control, however, I would re-arrange your Visual Studio project so that your shared code compiles to an assembly that your client and server assemblies use and depend on. Share code at the assembly level, not the code level.
If you really must keep your existing structure, I would use NTFS junctions (similar to UNIX-style soft links) to junction in the shared code where it needs to go. You would then add these junctions to your repository's ignore list (in .hgignore). Create a PowerShell script that you and other developers can run that will initialize your repository with the right junctions.

Related

Add as link with VisualSVN

I've got a solution in which I'm trying to create a 2nd executable. These two executable share most of the same files, but have a few different ones including resources and application icon, etc.
I created the 2nd project, and added the items as links.:
Right-click "Add existing item",
Browse to it,
Click the "Add" drop-down and select "Add as link".
Adding as links means that it just references the other file in the other folder and does not copy it.
Now, when I tried to commit my project VisualSVN / SVN tried to do an SVN add on those files in the logical path they belong to resulting in lots of errors that the file was not found. It caused the entire commit to fail and was a major pain in the ass.
Is there a good way I can add links to files without side-effects? All the files I'm trying to link to are already in the same repo.
Update
Maybe I should add more information about what I'm trying to accomplish because I'm open to any suggestion which helps me accomplish it.
I have a project structure something like this... Or I want it to be like this...
MyProject
/Common
BusinessDataObjects (svn:external)
ControlsLibrary (svn:external)
OtherCommmonLib1 (svn:external)
OtherCommonLib2 (svn:external)
/Modules
Module1
Module2
Module3
...
Application1
Application2 (shares all App1's files, except different .resx, icon, name, other minor differences)
SetupProject1 (includes app1 and certain module dlls)
SetupProject2 (includes app2 and certain module dlls)
The application is basically an empty shell (using Prism) which loads the modules installed in a /modules folder. I want both applications to be almost identical, but I want them to have different names and a different icon. I thought I could accomplish this by adding the files from the first project to the second as a link, and simply swapping a resource file which included the strings for the application window title, About dialog, etc. But then VisualSVN or whatever tried to SVN Add those items which I wasn't expecting.
I need to be able to develop the modules and the application's shell project. They are not stable in any way yet. I just want them to near copies of each other but with minor naming differences. I figured with two application projects, I could have two setup projects that included the output from each application and whichever modules are supposed to be included in that version of the software program.
I was trying to make this as foolproof as possible, and I'd like to avoid having to update external references to the same project. (I'm a bit confused about that as well, would I svn:external to the same repo?) That doesn't sound good, but this was my main idea on how to create two almost identical apps. I'm not sure how else I'll do it if I can't get my version control software to behave.
I had suggested oringally we only have one version of the software and have certain modules be upgrades, but there are some good reasons they can't really do that.
When you add a file to a Visual Studio project with "Add as link" it's expected that the file is not copied to the project's folder.
VisualSVN considers status of items in your working copy, even files which are not included in the current solution. However a linked file does not exist in a working copy, thus can't be tracked. It's out of version-control.
Since the files you attempt to link are already version-controlled (i.e. they exist in the SVN repository) it makes sense to use Externals Definitions (svn:externals property) to link them.
Also see TortoiseSVN Manual; it's description of svn:externals is really good.
You don't mention your environment. However, you mention you have a Solution. I'm assuming it's VisualStudio you're using.
Have you tried AnkhSVN which is a Source Control Provider for Subversion for VisualStudio? AnknSVN integrates into VisualStudio much like Microsoft's native version control systems of Visual SourceSafe and TeamFoundation. I believe you can use AnknSVN to do the linking you want since these links are really internal VisualStudio structures and not actual symbolic or hard links like you find in a Unix system.
I usually avoid links (I believe they're called Junctions on Windows) because they simply don't work across operating systems. Instead, you can use one of the following methods:
Use your build system to copy the files, or create the required links rather than your version control system.
Use svn:externals to do the linking. Careful with this because svn:externals are pointers to a Subversion URL.
For example, if I setup http://foo.com/svn/trunk/proj1 to have a svn:externals link to the head of http://foo.com/svn/trunk/proj2, and I create a tag for Project 1 by copying http://foo.com/svn/trunk/proj1 to http://foo.com/svn/tags/REL-1.2/proj1, that project is still pointing to the head of the trunk of proj2. Changes in Project 2 will change what I thought was a stable tag. Always point your svn:external to a stable revision.
I have no experience with VisualSVN, we use Ankhsvn which does not have that problem.
http://ankhsvn.open.collab.net/

Proper setup for visual studio and SVN

I am wanting to setup a project and potentially an existing project to be SVN version controlled. I am using uberSVN for the svn server. I have installed AnkhSVN for visual studio.
Currently, the team I am working with is using visual source safe and one of the problems we have is when someone adds a reference to a DLL, it modifies the project file as you would expect, but our paths are different between different team members (XP boxes, 7, you get the idea). What I was wanting is making the project file ignored when checking in/out so that we don't mess up the references for everyone else.
Is there a way I can make SVN ignore these files within the plugin? One of the side effects of this is a person would not know if a new file has been added in the project as this modifies the project file. Other than telling everyone "hey, you need to manually add this file to your project," is there a cleaner way of doing it?
If you copy the DLL to a folder inside your VS solution folder before linking to it, I think the project link will be relative not absolute. So you can check the DLL and the updated VS project into your configuration management and everyone should be able to share it.
You should start using virtual paths for development work; that way each team member can keep work-related files at any physical location but the virtual path (the one seen by tools is always the same.
For example, my team does all work under Q:\. My physical source for work is under physical path C:\Work\<project_name> where the project_name part depends on the project. When I want to work on a given project, I map the Q:\ virtual path to the right physical path using
subst q: c:\work\project_name
When I need to switch, I run a similar command. This way there's no need to worry about different paths on different computers. This worked very well for the whole team and eliminated most issues you describe above. The only thing you need to make sure is that everyone always uses the virtual path (Q:), not the physical path when dealing with project-related files. For my team it took about a week to get used to that, after that there were no more problems.
Your project file is an important part of your project so ignoring it in the source control tool will eventually lead to problems. I recommend you don't do it (even if you can).
Edit:
If you have DLL-s in different physical folders on different machines, the best choice is to copy those DLL-s (and their dependencies) to a known location. It's fine that they can't run from there, as long as the compiler finds them.
This known location could be inside your virtual path or a common physical path (if the same DLL-s are needed for multiple projects). You can use Dependency Walker to determine what dependencies you need for native DLL-s and Reflector for .NET DLL-s.
If the size/number of DLL-s is so large that creating a copy is not an option, you can actually tell AnkhSVN to ignore certain versioned files when committing changes. Right-click the file, select Subversion > Move to Change List > ignore-on-commit. After this the file will show up in the commit dialog unselected but you can still commit it if you manually select it.

Sharing a file between multiple locations

We are currently using Subversion (on Windows) for our source control but we examine switching to Mercurial. One problem is that we use externals in our repositories to share single files between multiple sub-projects. If one version of such a file is edited, the changes are propagated to each other version in our check-out. Is there a way to achieve the same in Mercurial, i.e. the same file in multiple locations? On Unix, this may be possible using some kind of links. But how about Windows?
Mercurial has the Subrepository features which is a little bit like svn externals.
The Mercurial feature is a more complicated than external in my point of view, but you can achieve the same goal with it and it is more flexible.
You can even use Subversion or Git repository as subrepo in Mercurial, so depending on what you're doing now, you could reuse your actual externals repo without any changes.
Everything is well explained in the linked documentation to have a good start with this functionnality !
BTW, symbolic links also exists on Windows : NTFS Symbolic link

Anhksvn + Visual Studio - working with linked files

I could use some advice.
I'm in the process of adopting subversion, and I'm trying to put some existing Visual Studio 2010 projects into a repository. I have the current version of AhnkSvn.
The projects I have are organised as;
VS2010_projects\Project_A
VS2010_projects\Project_B
VS2010_projects\Project_C
VS2010_projects\Common_code
Where Project_A, Project_B and Project_C may all refer to one or more files in "Common_Code"
In visual studio, these files will have been added using "add as link".
There is no actual project in "Common_code" just a collection of useful code files, which we're likely to re-use in different projects.
(If we have a module or class which is re-used in various projects, then we often keep a single master copy in 'common-code', and link to it.)
Visual Studio has no problem with this.
When I add any of the actual projects to subversion, all of their own files are added just fine, but the linked files are ignored.
(And as a consequence, if I then get a working copy of those files, then it's just the project files which get handled, I won't get a copy of the linked files.)
If I right click on any of the linked files, I the only subversion options I get are to refresh their status or to select the working folder.
I was wondering what the correct way to handle this situation was ?
Any advice would be much appreciated
Thanks !
Robert
if I understand your question correctly then I think SVN is acting in the desired way. A linked file is merely a reference to another file. That reference exists only in the .csproj file which is checked in. It would not make sense to have two copies of the same file in source control, and it could lead to versioning issues. The first time you checkout your repository doing a build on your projects should copy the files from Common_code to the places that they're linked.
As an aside we've had alot of random issues with .csproj linked files and SVN, and so try to avoid linked files where possible. A better way to re-use files across projects is obviously just to embed them in a library and then reference that library. This should work fine with the exception of certain files like Javascript/CSS.
Also you may want to check out SVN externals, a workmate mentioned this can be used to share common libraries between multiple projects, although as a disclaimer I haven't tried this myself and can't comment on the merits or drawbacks of the approach.
Thanks for the advice, I actually did something similar to your suggestion.
I didn't want to make a full blown library, but I did make up a dummy project, and put my shared files into that.
Then I added the dummy project to the repository.
AhnkSvn now seems to be satisfied that the linked files are under subversion control, and seems to handle them just fine.
(I haven't added any reference to the dummy project to my existing projects - they just use the linked files as before - but now AhnkSvn shows me their status, and allows me to get the latest version, and commit changes.)
I can see the case for having a proper library - but that would have meant modifying a large body of existing projects. This approach lets me get up and running with Subversion without requiring those changes first.

Structuring projects & dependencies of large winforms applications in C#

UPDATE:
This is one of my most-visited questions, and yet I still haven't really found a satisfactory solution for my project. One idea I read in an answer to another question is to create a tool which can build solutions 'on the fly' for projects that you pick from a list. I have yet to try that though.
How do you structure a very large application?
Multiple smallish projects/assemblies in one big solution?
A few big projects?
One solution per project?
And how do you manage dependencies in the case where you don't have one solution.
Note: I'm looking for advice based on experience, not answers you found on Google (I can do that myself).
I'm currently working on an application which has upward of 80 dlls, each in its own solution. Managing the dependencies is almost a full time job. There is a custom in-house 'source control' with added functionality for copying dependency dlls all over the place. Seems like a sub-optimum solution to me, but is there a better way? Working on a solution with 80 projects would be pretty rough in practice, I fear.
(Context: winforms, not web)
EDIT: (If you think this is a different question, leave me a comment)
It seems to me that there are interdependencies between:
Project/Solution structure for an application
Folder/File structure
Branch structure for source control (if you use branching)
But I have great difficulty separating these out to consider them individually, if that is even possible.
I have asked another related question here.
Source Control
We have 20 or 30 projects being built into 4 or 5 discrete solutions. We are using Subversion for SCM.
1) We have one tree in SVN containing all the projects organised logically by namespace and project name. There is a .sln at the root that will build them all, but that is not a requirement.
2) For each actual solution we have a new trunks folder in SVN with SVN:External references to all the required projects so that they get updated from their locations under the main tree.
3) In each solution is the .sln file plus a few other required files, plus any code that is unique to that solution and not shared across solutions.
Having many smaller projects is a bit of a pain at times (for example the TortoiseSVN update messages get messy with all those external links) but does have the huge advantage that dependancies are not allowed to be circular, so our UI projects depend on the BO projects but the BO projects cannot reference the UI (and nor should they!).
Architecture
We have completely switched over to using MS SCSF and CAB enterprise pattern to manage the way our various projects combine and interact in a Win Forms interface. I am unsure if you have the same problems (multiple modules need to share space in a common forms environment) but if you do then this may well bring some sanity and convention to how you architect and assemble your solutions.
I mention that because SCSF tends to merge BO and UI type functions into the same module, whereas previously we maintained a strict 3 level policy:
FW - Framework code. Code whose function relates to software concerns.
BO - Business Objects. Code whose function relates to problem domain concerns.
UI - Code which relates to the UI.
In that scenario dependancies are strictly UI -> BO -> FW
We have found that we can maintain that structure even while using SCSF generated modules so all is good in the world :-)
To manage dependencies, whatever the number of assemblies/namespaces/projects you have, you can have a glance at the tool NDepend.
Personnaly, I foster few large projects, within one or several solutions if needed. I wrote about my motivations to do so here: Benefit from the C# and VB.NET compilers perf
I think it's quite important that you have a solution that contains all your 80 projects, even if most developers use other solutions most of the time. In my experience, I tend to work with one large solution, but to avoid the pain of rebuilding all the projects each time I hit F5, I go to Solution Explorer, right-click on the projects I'm not interested in right now, and do "Unload Project". That way, the project stays in the solution but it doesn't cost me anything.
Having said that, 80 is a large number. Depending on how well those 80 break down into dicrete subsystems, I might also create other solution files that each contain a meaningful subset. That would save me the effort of lots of right-click/Unload operations. Nevertheless, the fact that you'd have one big solution means there's always a definitive view of their inter-dependencies.
In all the source control systems that I've worked with, their VS integration chooses to put the .sln file in source control, and many don't work properly unless that .sln file is in source control. I find that intriguing, since the .sln file used to be considered a personal thing, rather than a project-wide thing. I think the only kind of .sln file that definitely merits source control is the "one-big-solution" that contains all projects. You can use it for automated builds, for example. As I said, individuals might create their own solutions for convenience, and I'm not against those going into source control, but they're more meaningful to individuals than to the project.
I think the best solution is to break it in to smaller solutions. At the company I currently work for, we have the same problem; 80 projects++ in on solution. What we have done, is to split into several smaller solutions with projects belonging together. Dependent dll's from other projects are built and linked in to the project and checked in to the source control system together with the project. It uses more disk space, but disk is cheap. Doing it this way, we can stay with version 1 of a project until upgrading to version 1.5 is absolutely necessary. You still have the job with adding dll's when deciding to upgrade to a other version of the dll though. There is a project on google code called TreeFrog that shows how to structure the solution and development tree. It doesn't contain mush documentation yet, but I guess you can get a idea of how to do it by looking at the structure.
A method that i've seen work well is having one big solution which contains all the projects, for allowing a project wide build to be tested (No one really used this to build on though as it was too big.), and then having smaller projects for developers to use which had various related projects grouped together.
These did have depencies on other projects but, unless the interfaces changed, or they needed to update the version of the dll they were using, they could continue to use the smaller projects without worrying about everything else.
Thus they could check-in projects while they were working on them, and then pin them (after changing the version number), when other users should start using them.
Finally once or twice a week or even more frequently the entire solution was rebuild using pinned code only, thus checking if the integration was working correctly, and giving testers a good build to test against.
We often found that huge sections of code didn't change frequently, so it was pointless loading it all the time. (When you're working on the smaller projects.)
Another advantage of using this approach is in certain cases we had pieces of functionality which took months to complete, by using the above approach meant this could continue without interrupting other streams of work.
I guess one key criteria for this is not having lots of cross dependencies all over your solutions, if you do, this approach might not be appropriate, if however the dependencies are more limited, then this might be the way to go.
For a couple of systems I've worked on we had different solutions for different components. Each solution had a common Output folder (with Debug and Release sub-folders)
We used project references within a solution and file references between them. Each project used Reference Paths to locate the assemblies from other solutions. We had to manually edit the .csproj.user files to add a $(Configuration) msbuild variable to the reference paths as VS insists on validating the path.
For builds outside of VS I've written msbuild scripts that recursively identify project dependencies, fetch them from subversion and build them.
I gave up on project references (although your macros sound wonderful) for the following reasons:
It wasn't easy to switch between different solutions where sometimes dependency projects existed and sometimes didn't.
Needed to be able to open the project by itself and build it, and deploy it independently from other projects. If built with project references, this sometimes caused issues with deployment, because a project reference caused it to look for a specific version or higher, or something like that. It limited the mix and match ability to swap in and out different versions of dependencies.
Also, I had projects pointing to different .NET Framework versions, and so a true project reference wasn't always happening anyways.
(FYI, everything I have done is for VB.NET, so not sure if any subtle difference in behavior for C#)
So, I:
I build against any project that is open in the solution, and those that aren't, from a global folder, like C:\GlobalAssemblies
My continuous integration server keeps this up to date on a network share, and I have a batch file to sync anything new to my local folder.
I have another local folder like C:\GlobalAssembliesDebug where each project has a post build step that copies its bin folder's contents to this debug folder, only when in DEBUG mode.
Each project has these two global folders added to their reference paths. (First the C:\GlobalAssembliesDebug, and then C:\GlobalAssemblies). I have to manually add this reference paths to the .vbproj files, because Visual Studio's UI addes them to the .vbprojuser file instead.
I have a pre-build step that, if in RELEASE mode, deletes the contents from C:\GlobalAssembliesDebug.
In any project that is the host project, if there are non dlls that I need to copy (text files outputted to other project's bin folders that I need), then I put a prebuild step on that project to copy them into the host project.
I have to manually specify the project dependencies in the solution properties, to get them to build in the correct order.
So, what this does is:
Allows me to use projects in any solution without messing around with project references.
Visual Studio still lets me step into dependency projects that are open in the solution.
In DEBUG mode, it builds against open loaded projects. So, first it looks to the C:\GlobalAssembliesDebug, then if not there, to C:\GlobalAssemblies
In RELEASE mode, since it deletes everything from C:\GlobalAssembliesDebug, it only looks to C:\GlobalAssemblies. The reason I want this is so that released builds aren't built against anything that was temporarily changed in my solution.
It is easy to load and unload projects without much effort.
Of course, it isn't perfect. The debugging experience is not as nice as a project reference. (Can't do things like "go to definition" and have it work right), and some other little quirky things.
Anyways, that's where I am on my attempt to make things work for the best for us.
We have one gigantic solution on the source control, on the main branch.
But, every developer/team working on the smaller part of the project, has its own branch which contains one solution with only few projects which are needed. In that way, that solution is small enough to be easily maintenaced, and do not influence on the other projects/dlls in the larger solution.
However, there is one condition for this: there shouldn't be too much interconnected projects within solution.
OK, having digested this information, and also answers to this question about project references, I'm currently working with this configuration, which seems to 'work for me':
One big solution, containing the application project and all the dependency assembly projects
I've kept all project references, with some extra tweaking of manual dependencies (right click on project) for some dynamically instantiated assemblies.
I've got three Solution folders (_Working, Synchronised and Xternal) - given that my source control isn't integrated with VS (sob), this allows me to quickly drag and drop projects between _Working and Synchronised so I don't lose track of changes. The XTernal folder is for assemblies that 'belong' to colleagues.
I've created myself a 'WorkingSetOnly' configuration (last option in Debug/Release drop-down), which allows me to limit the projects which are rebuilt on F5/F6.
As far as disk is concerned, I have all my projects folders in just one of a few folders (so just one level of categorisation above projects)
All projects build (dll, pdb & xml) to the same output folder, and have the same folder as a reference path. (And all references are set to Don't copy) - this leaves me the choice of dropping a project from my solution and easily switching to file reference (I've got a macro for that).
At the same level as my 'Projects' folder, I have a 'Solutions' folder, where I maintain individual solutions for some assemblies - together with Test code (for example) and documentation/design etc specific to the assembly.
This configuration seems to be working ok for me at the moment, but the big test will be trying to sell it to my colleagues, and seeing if it will fly as a team setup.
Currently unresolved drawbacks:
I still have a problem with the individual assembly solutions, as I don't always want to include all the dependent projects. This creates a conflict with the 'master' solution. I've worked around this with (again) a macro which converts broken project references to file references, and restores file references to project references if the project is added back.
There's unfortunately no way (that I've found so far) of linking Build Configuration to Solution Folders - it would be useful to be able to say 'build everything in this folder' - as it stands, I have to update this by hand (painful, and easy to forget). (You can right click on a Solution Folder to build, but that doesn't handle the F5 scenario)
There is a (minor) bug in the Solution folder implementation which means that when you re-open a solution, the projects are shown in the order they were added, and not in alphabetical order. (I've opened a bug with MS, apparently now corrected, but I guess for VS2010)
I had to uninstall the CodeRushXPress add-in, because it was choking on all that code, but this was before having modified the build config, so I'm going to give it another try.
Summary - things I didn't know before asking this question which have proved useful:
Use of solution folders to organise solutions without messing with disk
Creation of build configurations to exclude some projects
Being able to manually define dependencies between projects, even if they are using file references
This is my most popular question, so I hope this answer helps readers. I'm still very interested in further feedback from other users.

Resources