I am trying to create a custom build activity in C# that gets the list of files in the changesets from a build that was triggered by a check-in action in TFS 2010 and move those files from the SourcesDirectory to another location. The question is whether it is possible to retrieve the list of files that the user checks in to TFS 2010 that triggers a build so that I can loop through the files and move them to another location? So far, I have no luck.
Thanks much for any answers or help!
Thanks Loïc Faure-Lacroix for the comments. I guess my question was too broad so nobody answered my question.
It took me a while to get to where I am now and here’s what I’ve managed to do so far. I got the idea from the following links to take the Changesets as a parameter for my custom activity. I also took the SourcesDirectory as a param which I could obtain from inside the “Run On Agent” sequence.
http://blogs.msdn.com/b/codejunkie/archive/2010/09/02/custom-build-activity-for-tfs-2010-to-send-email-with-build-details-part-1.aspx
http://blogs.msdn.com/b/codejunkie/archive/2010/09/15/custom-build-activity-for-tfs-2010-to-send-email-with-build-details-part-2.aspx
[RequiredArgument]
[Browsable(true)]
public InArgument<IList<Changeset>> Changesets { get; set; }
[RequiredArgument] // The source directory to copy the files from
public InArgument<string> SourcesDirectory { get; set; }
I then needed to loop through the changeset to get the list of items that were checked in to TFS. However, the items I got from the changeset contain the server path, namely, something like “$/MainProj/SubProj/contactus/contact.htm” so I needed a way similar to the ConvertWorkspaceItem activity that can convert the server path to the real local build path on the build server. Does anyone know how the ConvertWorkspaceItem actually work? The SourcesDirectory has the path similar to this (which I am not sure whether always has the same format or will change based on projects or how build server was configured.): C:\Builds\1\SubProj\Sources\contactus
Since I could not find a proper way to convert the paths so I used an ugly way of basic substring search and replacement…
Once I looped through the changset, converted the server path to local source path, I was able to copy those files just checked in to TFS to another location such as a folder on our development server.
Then I ran into one big obstacle. I got the access denied error from the build when I tested with creating a new folder with a few new files in it and checking those in to trigger the build. It seemed that some process or thread that created the new folder in TFS and checked the files in still lock the folder when the build started to run, which I assumed is another thread… If the checked in files were in an existing folder, everything worked fine… Could anyone please share some insights?
Thanks!
Related
Edit: I just read that Microsoft products often delete and create a new file when saving, so we may need a completely different solution than below...
I'm writing some code to track file and folder changes on both Windows and Mac while my app is running, but it also needs to detect changes if it's not running.
I'm able to do this on Windows by obtaining folder and file ID's using the following post:
Getting a Folder ID C#
Now I need a solution for Mac, but after searching I've come up a bit empty. I can't find anything regarding a system-wide folder/file ID. The closest I came to a solution was using some sort of bookmark that could track the file as described below, but I haven't started yet:
https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/AccessingFilesandDirectories/AccessingFilesandDirectories.html#//apple_ref/doc/uid/TP40010672-CH3-SW10
Seems I would have to store these bookmarks as Alias files to recall when the program starts back up.
Are there any other options for getting a global file/folder ID on Mac using C#?
You can use NSFileManager.GetAttributes to obtain an "inode" of the file (as Jason's comment calls out)
Note: Of course inodes change if moved across volumes, if a program that edits a file performs a delete and recreate vs. a replace, etc...
Example:
var ns = NSFileManager.DefaultManager;
var attribs = ns.GetAttributes("/Users/sushi/Desktop/foo.txt");
Console.WriteLine(attribs.SystemFileNumber);
File.Move("/Users/sushi/Desktop/foo.txt", "/Users/sushi/Desktop/foo2.txt");
var attribs2 = ns.GetAttributes("/Users/sushi/Desktop/foo2.txt");
Console.WriteLine(attribs2.SystemFileNumber);
I've got a program that digs inside the Local App Data folder of another program, pulls out some files, and then pushes them to Azure Blob Storage. I've already developed the rest of the program, but the intent of the application is to be as brainless as possible for the user- just a simple double click and the files have been uploaded.
At the moment the program requires manual input to find the correct folder in Local App Data. The Problem lies in that the name of the folder isn't always completely constant.
The folder's name always starts with com.company.propelics, followed by a series of randomized numbers and characters. I've already checked and there's no way to reproduce the randomization for each user. Within that folder, the folder structure is always constant- so the program would never have an issue finding the files once the original folder is found.
Is there a way to either scan the folders in Local App Data for the subfolders that will always exist, or take what is constant (com.company.propelics) and select the folder with that in the name?
Thanks for the help
IEnumerable<string> candidates = Directory
.EnumerateDirectories(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"com.company.propelics*");
Then
var folderPath = candidates.FirstOrDefault();
or something more complicated if there's disambiguation to perform...
Running my C# application from Visual studio works fine (in this respect)
But when installing the application in my system (win7, .NET 4.0) I get problems with the cache.
These are the errors I get:
LogMessageCallback. Message:20:43:03.988 E [playlist:1978] Unable to save file: playlist.bnk
LogMessageCallback. Message:20:43:03.988 E [social-mgr:830] Unable to save file: social_stream.bnk
LogMessageCallback. Message:20:46:31.034 E [user_cache:107] Unable to save file: user-cache.bnk
LogMessageCallback. Message:20:43:04.988 I [c:/Users/spotify-buildagent/BuildAgent/work/1e0ce8a77adfb2dc/client/core/protocol/file_streamer_simple.cpp:769] Request for file 57a6ab34bad26645e2345a610ae652fe77f82afb complete (code: 0)
I have tried to deleted the entire cache library and it gets recreated when I start the app, so it can't be a matter of file privilege.
Since the cache does not seem to be valid my playlists are not accessible to me at startup.
I do log out properly.
Any explanation/workaround?
I think I've got it...
I search for the playlist.bnk file on my disk and found one under Spotify\bin\Debug\cache_location\Users\bes51659-user, that is from where I run my project with visual studio. "cache_location" in the path directed me to the settings_location argument in the config struct when creating the session. I had set it to const string "cache_location". I must have understood the explanation wrong:
https://developer.spotify.com/docs/libspotify/12.1.51/structsp__session__config.html#a342532432040d476aaaf73f10893d23b
The location where Spotify will write setting files and per-user cache items. This includes playlists, track metadata, etc. 'settings_location' may be the same path as 'cache_location'. 'settings_location' folder will not be created (unlike 'cache_location'), if you don't want to create the folder yourself, you can set 'settings_location' to 'cache_location'.
(a bit contradictory that the "cache_location" catalog was actually created under debug!)
The comment must mean that if I reuse the same location for setting_location as for cache_location I do not have to create it as it has already been created!
I do not know if libspotify did not have permissions to create the catalog "cache_location" under "program files", or if it expected it to be there and did not find it. But it does not matter. I have now changed both the locations to "c:\mySpotify" in the config struct and problem solved...
My only excuse is that google tells me that I'm not the first to have fallen into this pithole.
I keep having a situation where gets annoying (with TFS). I searched for "TFS" and "Recursive folder/files" but didn't find something similar in SOF and then good it but not exactly what I need.
I have checked out a project from TFS (#1) on my local machine and then after some modifications did update them on a new TFS (#2). Later noticed on TFS #2 have:
Solution folder
folder 1/folder 2/files
folder 2
folder 3/folder 3/files
I checked back on TFS #1 things were OK however, for a reason when it gets to my local drive it can get recursive. Anybody knows what I have done wrong? or any settings are involved?
One thing is that folders which go recursive are other developers projects.
Thank you!
I have the following situation.
I programmatically create a temporary workspace using TFS. I then map it to a spot on my local machine so that I can be able to checkin/checkout files. Since the mapping to the local drive through the workspace is what creates the file structure. What is the way to delete the mapping through the workspace object that I created?
Ive tried the following.
WorkingFolder tempFolder = workspace.getWorkingFolderForServerItem(serverItem);
workspace.DeleteMapping(tempFolder);
Stepping through in debug mode, the tempFolder Object I make holds the correct local mapping as well as the correct server mapping. I cant seem to get it to delete the local content though. Is this mostly correct or do you suggest something completely different?
In TFS, the trick to deleting files locally and telling the server that you do not have them anymore is to get the files at Changeset 1 (i.e. before they existed). In code that would be something like:
workspace.Get(
new string[] {"C:\\LocalPath"},
new ChangesetVersionSpec(1),
RecursionType.Full,
GetOptions.None);
See the following blog post where I explain this concept some more:
TFS Top Tip #11 - Removing source control files from your local file system
That said, if the workspace is just temporary and you do not need it anymore then doing a workspace.Delete() followed by a traditional file delete is a perfectly good way of doing things. If you were trying to keep the workspace around you could get into trouble though (because TFS thinks those files are still in your local workspace unless you tell it that they are not)
Since the mapping to the local drive through the workspace is what creates the file structure.
I think you have this wrong. The local folders (and files) are created only when you perform the get after the mapping is created (whether from the Team Explorer GUI, "tf.exe get", or otherwise).
After deleting the workspace mapping, you will need to create code to delete the files and folders yourself.
Thanks to Richard, I decided to not try and delete the file through the workspace.
Given:
WorkingFolder tempFolder = workspace.getWorkingFolderForServerItem(serverItem);
I ended up doing:
File.setAttributes(tempFolder.LocalItem, FileAttributes.normal)//Get rid of read-only
File.Delete(tempFolder.LocalItem);
Thanks for the help!