commit files not working properly - c#

I m trying to commit changes to the project to my svn server but it doesnt seem to work.
The Test:
I run the code below with the folder where nothing has been changed and nothing happens as expected, Then I create a new folder and then run the code again, this time nothing seems to happen, the code runs and returns without the error showing it worked.
public bool svnCommitProject(String project, String message)
{
using (SvnClient client = new SvnClient())
{
try
{
SvnCommitArgs args = new SvnCommitArgs();
args.LogMessage = message;
client.Authentication.ForceCredentials(Properties.Settings.Default.Username, Properties.Settings.Default.Password);
return client.Commit(Properties.Settings.Default.LocalFolderPath + Properties.Settings.Default.Username + #"\" + project, args);
}
catch
{
MessageBox.Show("ERROR");
return false;
}
}
}
Suspected Problem:
From looking at this and google i suspect that the problem exists because the file hasnt been "added" to svn control, but im not sure.
Is this the case? and if so how would I go about adding the files which need to be added? I also assume that something similar would be needed for files which are deleted/modified, is this correct and how would I add this in too?

See Find files not added to subversion
Yes, files just dropped into the local working directory doesn't tell the SVN to commit to.
Collection<SvnStatusEventArgs> filesStatuses = new Collection<SvnStatusEventArgs>();
if (!client.GetStatus(localDir, new SvnStatusArgs
{
Depth = SvnDepth.Infinity,
RetrieveRemoteStatus = true,
RetrieveAllEntries = true
}, out workDirFilesStatus))
{
throw new SvnOperationCanceledException("SvnClient.GetStatus doesn't return anything.");
}
filesStatuses.Where(i => i.LocalContentStatus == SvnStatus.NotVersioned).ToList().ForEach(i => svnC.Add(i.Path));
filesStatuses.Where(i => i.LocalContentStatus == SvnStatus.Missing).ToList().ForEach(i => svnC.Delete(i.Path));

Related

TFS - Get latest code in a folder

I am using the TFS API to get latest code files, directories, .csproj files, etc. under a TFS-bound folder.
For the same, I use something like the following:
var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new
Uri(ConfigurationManager.AppSettings["TFSUrl"]));
tfs.EnsureAuthenticated();
var vsStore = tfs.GetService<VersionControlServer>();
string workingFolder = #"C:\TFS\SolutionFolder";
Workspace wsp = vsStore.TryGetWorkspace(workingFolder);
if (wsp != null)
{
ItemSet items = vsStore.GetItems(workingFolder, VersionSpec.Latest, RecursionType.Full);
string relativePath = workingFolder + #"/";
foreach (Item item in items.Items)
{
string relativePath1 = item.ServerItem.Replace("$/TFS/SolutionFolder", relativePath);
if (item.ItemType == ItemType.Folder)
{
Directory.CreateDirectory(relativePath1);
}
else
{
item.DownloadFile(relativePath1);
}
}
}
Now, I get the items to download and then download happens. However, I want it to be like how VS handles it - if (and only if) there is a change in a file/folder, then only download the same. With this code, I always get 'n' number of files/folders in that folder and then I overwrite the same. Wrong approach, I know. I can, however, modify this code to check for the folder's or file's last change time and then choose to either overwrite it or ignore it. That's an option, albeit a bad one at that.
Now, what I would ideally like is to get ONLY the list of files/folders that actually need to be changed i.e. the incremental change. After that, I can choose to overwrite/ignore each item in that list. So, in the present case, if a new file/folder is created (or one of the existing ones got changed inside $/TFS/SolutionFolder i.e. in the sever), then only I want to pull that item in the list of files/folders to change(and decide what I want to do with it inside C:\TFS\SolutionFolder).
Also, is using one of the overloads of VersionControlServer.QueryHistory() an option? I had something like this:
(latestVersionIdOf $/TFS/SolutionFolder) - (existingVersionIdOf C:\TFS\SolutionFolder) = (Versions that I'd go out and get back from the server, for that folder)
in mind.
Any pointers will be very helpful. Thanks!
Just use Workspace.Get() or overload method (wsp.Get()), it just update updated files.
I don't think we can achieve that. If the files are downloaded to a folder without in source control, there are no versions compared within the folder, even if the folder is in source control, the behavior is just download also no version compare actions. So, it will download all the files ever time and then overwrite the same ones.
In VS, the files are all in TFS source control system, so when we Get Latest Version the changed/added files will be retrieved from TFS. If you want to get the same behavior as VS handles, you can use the tf get command. See Get Command
You can reference this article to use the tf get command :
get-latest-version-of-specific-files-with-tfs-power-tools
Update :-
var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(ConfigurationManager.AppSettings["TFSUrl"]));
tfs.EnsureAuthenticated();
var vsStore = tfs.GetService<VersionControlServer>();
string workingFolder = ConfigurationManager.AppSettings["LocalPathToFolder"]; // C:\TFS\SolutionFolder
string tfsPathToFolder = ConfigurationManager.AppSettings["TFSPathToFolder"]; // $/TFS/SolutionFolder
Workspace wsp = vsStore.GetWorkspace(workingFolder);
if (wsp != null)
{
ItemSpec[] specs = { new ItemSpec(tfsPathToFolder, RecursionType.Full) };
ExtendedItem[][] extendedItems = wsp.GetExtendedItems(specs, DeletedState.NonDeleted, ItemType.Any);
ExtendedItem[] extendedItem = extendedItems[0];
var itemsToDownload = extendedItem.Where(itemToDownload => itemToDownload.IsLatest == false);
foreach (var itemToDownload in itemsToDownload)
{
try
{
switch (itemToDownload.ItemType)
{
case ItemType.File:
if (itemToDownload.LocalItem != null)
{
vsStore.DownloadFile(itemToDownload.SourceServerItem, itemToDownload.LocalItem);
}
else
{
string localItemPath = itemToDownload.SourceServerItem.Replace(tfsPathToFolder,
workingFolder);
vsStore.DownloadFile(itemToDownload.SourceServerItem, localItemPath);
}
break;
case ItemType.Folder:
string folderName = itemToDownload.SourceServerItem.Replace(tfsPathToFolder, workingFolder);
if ((!string.IsNullOrEmpty(folderName)) && (!Directory.Exists(folderName)))
{
Directory.CreateDirectory(folderName);
}
break;
}
}
catch (Exception e)
{
File.AppendAllText(#"C:\TempLocation\GetLatestExceptions.txt", e.Message);
}
}
}
This code works well, except:
a. Whenever it downloads the latest copy of, let's say a file, it 'checks it out' in TFS :(
b. For some items, it throws errors like 'Item $/TFS/SolutionFolder/FolderX/abc.cs was not found in source control at version T.' - I have to find out what the exact cause of this issue is, though.
Any ideas on how to get around these two issues or any other problems you see with this code? Thanks!

SharpSVN.Merge() Not Working, Returns true But not able to see changes in Code

I am trying To Merge changes From SVN Folder to My Local folder which has previous revision code and new changes. Below Method takes SrcUrl and Local Path of Folder which has new changes and srcrev holds Revision Number that needs to be merged from svn to my local folder.
SVN.Merge() returns True but am not able to see any code changes in my local folder after merge.
Can anyone please tell me where am doing mistake.
public void Merge(String SrcUrl,String localpath,long SrcRev)
{
using (SvnClient client = new SvnClient())
{
try
{
SvnMergeArgs mergeArgs = new SvnMergeArgs();
mergeArgs.Depth = SvnDepth.Infinity;
//Attaching the events
mergeArgs.Notify += new EventHandler<SvnNotifyEventArgs>(Merge_Notify);
mergeArgs.SvnError += new EventHandler<SvnErrorEventArgs>(Merge_Error);
mergeArgs.Conflict += new EventHandler<SvnConflictEventArgs>(Merge_Confilct);
mergeArgs.Force = false;
SvnRevisionRange svnRange = new SvnRevisionRange(SrcRev, SrcRev);
SvnUriTarget MyTarget = new SvnUriTarget(new Uri(SrcUrl));
if( client.Merge(localpath, MyTarget, svnRange, mergeArgs))
MessageBox.Show("Merged successfully");
}
catch (SvnException se)
{
MessageBox.Show(se.Message,"svn merge error",MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
}
Was the change already merged before?
Subversion tracks whatever is already merged in the 'svn:mergeinfo' property, and if the change is already merged you just get success, just like with any other Subversion client.
Note that you always want to merge a revision range.. you merge the changes between two different revisions. The svn client implements its -c argument by passing the range of the passed revision minus 1, to the revision as that happens to be what is changed in that specific revision.

Replacing a file with a new file of the same name but different content in TFS via C#

i´m currently working on a programm which updates templates on our companies Team Foundation Server. I am having those new templates locally on my disk and want to replace the existing ones on the server. I was trying different approaches and this is my newest version. The problem is that either
the new file is "in use" when accessing it through coding in c#(while not in use when i try to replace it in runtime using the normal explorer).
the replacement is not appearing in the pending changes, the pendingChanges array is initial.
using (var tfs = TeamFoundationServerFactory.GetServer("myserver"))
{
var versionControlServer = tfs.GetService(typeof(VersionControlServer)) as VersionControlServer;
// Create a new workspace for the currently authenticated user.
var workspace = versionControlServer.CreateWorkspace("Temporary Workspace", versionControlServer.AuthorizedUser);
try
{
// Check if a mapping already exists.
var workingFolder = new WorkingFolder("$serverpath", #"c:\tempFolder");
// Create the mapping (if it exists already, it just overides it, that is fine).
workspace.CreateMapping(workingFolder);
workspace.Get(VersionSpec.Latest, GetOptions.GetAll);
string[] paths = new string[1];
paths[0] = "test.pdf";
workspace.PendEdit(paths, RecursionType.Full, null, LockLevel.None);
// Go through the folder structure defined and create it locally, then check in the changes.
CreateFolderStructure(workspace, workingFolder.LocalItem);
// Check in the changes made.
int a = workspace.CheckIn(workspace.GetPendingChanges(), "This is my comment");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
// Cleanup the workspace.
workspace.Delete();
// Remove the temp folder used.
Directory.Delete(#"C:\tempFolder", true);
}
}
}
static void CreateFolderStructure(Workspace workspace, string initialPath)
{
workspace.PendDelete("$serverpath/test.pdf", RecursionType.None);
File.Copy(#"C:\test\testnew.pdf", #"C:\tempfolder\test", true);
workspace.PendAdd(#"C:\tempfolder\test.pdf");
}
I found a solution to the problem. The workspace which was used by "authorizedUser" was obviously not enough.. I found out that a need a TeamFoundationIdentity to do it. Here is a guide on how to fix the issue.
http://blogs.msdn.com/b/taylaf/archive/2010/03/29/using-tfs-impersonation-with-the-version-control-client-apis.aspx

"There is no working folder mapping" error when accessing TFS

I'm working on an application that can create and add items to TFS.
My files get created correctly and in the correct location, however the Workspace.PendAdd method only works for one specific workspace, other workspaces give me the "There is no working folder mapping" error.
The method I am using is PendAdd(string filepath, bool recursive) so I pass in a directory to be added and would expect to add both the directory and its files as a pending add in TFS.
Both workspaces are identical in everything but name, neither have any files currently checked out and neither contain any files.
From my google searches I have found that there may be an issue when adding files to a workspace mapped to $/ but the workspace I am using is mapped to $/TFSFiles/ and so far nothing else seems likely.
The code for my PendAdd method is :
private IEnumerable<PendingChange> PendAddFileToTfs(string newFilename)
{
var previousPendingChanges = new List<PendingChange>(_selectedWorkspace.GetPendingChanges());
var changesAdded = _selectedWorkspace.PendAdd(Path.GetDirectoryName(newFilename), true);
var pendingAdds = new List<PendingChange>(_selectedWorkspace.GetPendingChanges());
var itemsToCheckIn = pendingAdds.Except(previousPendingChanges);
return itemsToCheckIn;
}
The method fails at the _selectedWorkspace.PendAdd line. I debugged and verified it is the correct local path and correct workspace.
Can someone point me in the right direction here?
EDIT:
The _selectedWorkspace variable is set by the user.
I get a list of all available workspaces via this code:
_workspaces = _versionControl.QueryWorkspaces(null, _versionControl.AuthorizedUser,environment.MachineName);
I then show a list of workspaces in a combobox and allow the user to select one.
This calls this method:
public void SetWorkspace(string workspaceName)
{
_selectedWorkspace = _workspaces.FirstOrDefault(ws => ws.Name.Equals(workspaceName));
}
You need to create a local workspace before you can add pendAdd files to TFS. I am not sure where _selectedWorkspace is coming from but it looks like it is not configured properly. Although I don't have a c# version to hand I do have a version in PowerShell that calls c#... should give you the way to go.
function New-TfsTeamProjectRootFolder {
Param(
[Microsoft.TeamFoundation.Client.TfsTeamProjectCollection] $TfsCollection,
[Microsoft.TeamFoundation.Server.ProjectInfo] $TfsTeamProject,
[String] $GlobalEntryValue
)
$TempWorkspaceName = "Create-TfsTeamSourceFolder"
$TempFolder = "c:\temp\$TempWorkspaceName"
$ServerFolder = "$/$($TfsTeamProject.Name)"
$TfsVersionControl = Get-TfsVersionControlServer $TfsCollection
try {
$workspace = $TfsVersionControl.GetWorkspace($TempFolder )
} catch {
$workspace = $TfsVersionControl.CreateWorkspace($TempWorkspaceName);
$workspace.Map($ServerFolder, $TempFolder);
}
$NewFolder = "$TempFolder\$GlobalEntryValue";
try {
$SourceItem = $TfsVersionControl.GetItem("$ServerFolder/$GlobalEntryValue")
} catch {
New-Item -ItemType Directory -Force -Path $NewFolder;
$workspace.PendAdd($NewFolder, $true);
$pendingChanges = $workspace.GetPendingChanges();
$changesetNumber = $workspace.CheckIn($pendingChanges, "Added folder for '$GlobalEntryValue'");
$SourceItem = $TfsVersionControl.GetItem("$ServerFolder/$GlobalEntryValue")
}
$workspace.Delete()
Return $SourceItem
}
Again I am not sure why your code is not working as I think the issue is in the greater context than we can see in the example above.

Programmatically get pending changes for a specific folder in a specific project?

I have been playing around with TFS for a while because I need to upload/check in specific files and folders into various locations on the TFServer after they have been created and placed locally. I am mapping the workspace and everything and I get a bunch of changes from PendingChanges but not the ones I want and not where I want. The problem is really annoying because for every check in process I only want to work on a specific folder or file in a specific location that is already mapped. I am gonna paste part of the code here for reference.
using (TfsTeamProjectCollection collection = new TfsTeamProjectCollection(serverUri, _cred))
{
VersionControlServer versionControl = (VersionControlServer)collection.GetService(typeof(VersionControlServer));
string machineName = Environment.MachineName;
string currentUserName = Environment.UserName;
Workspace myWorkspace = versionControl.GetWorkspace(machineName, currentUserName);
// tried this from Stack but didn't work.
//PendingChange[] changes = myWorkspace.GetPendingChanges().Where(x => x.LocalOrServerFolder.Contains(localPath)).ToArray();
PendingChange[] changes = myWorkspace.GetPendingChanges();
if (changes.Length != 0)
{
foreach (PendingChange c in changes)
{
rt.Text += " path: " + c.LocalItem + ", change: " + PendingChange.GetLocalizedStringForChangeType(c.ChangeType) + "\n";
}
}
else
{
rt.Text += "This didn't work.";
}
}
Basically I want to throw a folder or file at my TFS class and let it check if the file or folder is up to date or present on the TFS and act accordingly. I hope I have described the problem thoroughly.
I think that my answer will not response fully you question, but if you want to get pending changes for a specific folder, you can use something like this..
PendingChange[] changes = myWorkspace.GetPendingChanges(localPath, RecursionType.Full, false);

Categories

Resources