public override void OnExecute(CommandEventArgs e) { List<SvnItem> items = new List<SvnItem>(e.Selection.GetSelectedSvnItems(true)); e.GetService<IProgressRunner>().RunModal("Running Cleanup", delegate(object sender, ProgressWorkerArgs a) { HybridCollection<string> wcs = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); foreach (SvnItem item in items) { if (!item.IsVersioned) continue; SvnWorkingCopy wc = item.WorkingCopy; if (wc != null && !wcs.Contains(wc.FullPath)) wcs.Add(wc.FullPath); } SvnCleanUpArgs args = new SvnCleanUpArgs(); args.ThrowOnError = false; foreach (string path in wcs) a.Client.CleanUp(path, args); }); }
public DocumentLock LockDocuments(IEnumerable <string> paths, DocumentLockType lockType) { if (paths == null) { throw new ArgumentNullException("paths"); } HybridCollection <string> locked = new HybridCollection <string>(StringComparer.OrdinalIgnoreCase); HybridCollection <string> ignoring = new HybridCollection <string>(StringComparer.OrdinalIgnoreCase); HybridCollection <string> readOnly = new HybridCollection <string>(StringComparer.OrdinalIgnoreCase); foreach (string path in paths) { SccDocumentData dd; if (_docMap.TryGetValue(path, out dd)) { if (!locked.Contains(path)) { locked.Add(path); } if (!ignoring.Contains(path) && dd.IgnoreFileChanges(true)) { ignoring.Add(path); } if (lockType >= DocumentLockType.ReadOnly && !readOnly.Contains(path) && !dd.IsReadOnly()) { // Don't set read-only twice!!! if (dd.SetReadOnly(true)) { readOnly.Add(path); } } } } return(new SccDocumentLock(this, locked, ignoring, readOnly)); }
IDictionary <string, int> GetNumberValues(string regKey, string subKey) { if (string.IsNullOrEmpty(regKey)) { throw new ArgumentNullException("regKey"); } if (string.IsNullOrEmpty(subKey)) { throw new ArgumentNullException("subKey"); } IDictionary <string, int> values; lock (_lock) { subKey = regKey + "\\" + subKey; using (RegistryKey reg = OpenHKCUKey(subKey)) { if (reg == null) { return(null); } HybridCollection <string> hs = new HybridCollection <string>(); hs.AddRange(reg.GetValueNames()); values = new Dictionary <string, int>(hs.Count); foreach (string item in hs) { int width; if (RegistryUtils.TryGetIntValue(reg, item, out width) && width > 0) { values.Add(item, width); } } } } return(values); }
internal void OnSccCleanup(CommandEventArgs e) { _registeredSccCleanup = false; EnsureLoaded(); if (_delayedDelete != null) { IEnumerable <string> files = _delayedDelete; _delayedDelete = null; using (SvnSccContext svn = new SvnSccContext(this)) { foreach (string node in files) { if (!SvnItem.PathExists((node))) { svn.MetaDelete(node); } } } } }
private void AddActivitySubscription(ActivityStateQuery query) { _trackingRecordPreFilter.TrackActivityStateRecords = true; foreach (string state in query.States) { if (string.CompareOrdinal(state, "*") == 0) { _trackingRecordPreFilter.TrackActivityStateRecordsClosedState = true; _trackingRecordPreFilter.TrackActivityStateRecordsExecutingState = true; break; } if (string.CompareOrdinal(state, ActivityStates.Closed) == 0) { _trackingRecordPreFilter.TrackActivityStateRecordsClosedState = true; } else if (string.CompareOrdinal(state, ActivityStates.Executing) == 0) { _trackingRecordPreFilter.TrackActivityStateRecordsExecutingState = true; } } if (_activitySubscriptions == null) { _activitySubscriptions = new Dictionary <string, HybridCollection <ActivityStateQuery> >(); } HybridCollection <ActivityStateQuery> subscription; if (!_activitySubscriptions.TryGetValue(query.ActivityName, out subscription)) { subscription = new HybridCollection <ActivityStateQuery>(); _activitySubscriptions[query.ActivityName] = subscription; } subscription.Add((ActivityStateQuery)query); AddActivityName(query.ActivityName); }
bool PerformRevisionChanges(CommandEventArgs e) { long min = long.MaxValue; long max = long.MinValue; int n = 0; HybridCollection <string> changedPaths = new HybridCollection <string>(); foreach (ISvnLogItem item in e.Selection.GetSelection <ISvnLogItem>()) { min = Math.Min(min, item.Revision); max = Math.Max(max, item.Revision); n++; } if (n > 0) { ExecuteDiff(e, _ctrl.Origins, new SvnRevisionRange(n == 1 ? min - 1 : min, max)); return(true); } return(false); }
public IEnumerable <string> GetAllFiles() { ThreadHelper.ThrowIfNotOnUIThread(); HybridCollection <string> mapped = null; yield return(FullPath); SccProjectFileReference rf = FirstReference; while (rf != null) { IList <string> subFiles = rf.GetSubFiles(); if (subFiles.Count > 0) { if (mapped == null) { mapped = new HybridCollection <string>(StringComparer.OrdinalIgnoreCase); mapped.Add(FullPath); } foreach (string sf in subFiles) { if (mapped.Contains(sf)) { continue; } mapped.Add(sf); yield return(sf); } } rf = rf.NextReference; } }
public bool SaveAllDocumentsExcept(IEnumerable <string> paths) { if (paths == null) { throw new ArgumentNullException("paths"); } HybridCollection <string> openDocs = new HybridCollection <string>(StringComparer.OrdinalIgnoreCase); HybridCollection <string> dontSave = new HybridCollection <string>(StringComparer.OrdinalIgnoreCase); openDocs.UniqueAddRange(_docMap.Keys); dontSave.UniqueAddRange(paths); bool ok = true; foreach (string name in openDocs) { SccDocumentData data; if (dontSave.Contains(name)) { continue; } if (!_docMap.TryGetValue(name, out data)) { continue; // File closed through saving another one } if (!data.SaveDocument(RunningDocumentTable)) { ok = false; } } return(ok); }
/// <summary> /// Gets the selected files; yielding for each result to allow delay loading /// </summary> /// <param name="recursive"></param> /// <returns></returns> IEnumerable <string> InternalGetSelectedFiles(bool recursive) { ThreadHelper.ThrowIfNotOnUIThread(); HybridCollection <string> foundFiles = new HybridCollection <string>(StringComparer.OrdinalIgnoreCase); foreach (SelectionItem i in GetSelectedItems(recursive)) { string[] files; if (SelectionUtils.GetSccFiles(i, out files, true, true, null)) { foreach (string file in files) { if (!foundFiles.Contains(file)) { foundFiles.Add(file); yield return(file); } } } } }
// Remove the timer from the table, and set expiration date to a new value. public void RetryTimer(Bookmark bookmark) { // This value controls how many seconds do we retry const int retryDuration = 10; // When IOThread Timer calls back, it might call RetryTimer timer if ResumeBookmark returned notReady // In another thread, we may be in the middle of persistence. // During persisting, we will mark the table as immutable // After we are done writing to the database, we will buffer the remove request // Meanwhile, since we are not scheduling any IOThreadTimers, // we can only have at most one pending Remove request // We don't want to remove if (!_isImmutable) { // We only retry the timer IFF no one has removed it from the table // Otherwise, we are just retrying a timer that doesn't exist if (_sortedTimerList.ContainsKey(bookmark)) { this.RemoveTimer(bookmark); // Update it to the retry time and put it back to the timer list this.AddTimer(TimeSpan.FromSeconds(retryDuration), bookmark); } } else { if (_pendingRetryBookmark == null) { _pendingRetryBookmark = new HybridCollection <Bookmark>(bookmark); } else { _pendingRetryBookmark.Add(bookmark); } } }
internal void HandleEvent(AnkhCommand command) { List <SccProject> dirtyProjects; HybridCollection <string> dirtyCheck; HybridCollection <string> maybeAdd; SvnSccProvider provider = GetService <SvnSccProvider>(); lock (_lock) { _posted = false; _onIdle = false; if (provider == null) { return; } dirtyProjects = _dirtyProjects; dirtyCheck = _dirtyCheck; maybeAdd = _maybeAdd; _dirtyProjects = null; _dirtyCheck = null; _maybeAdd = null; } if (dirtyCheck != null) { foreach (string file in dirtyCheck) { DocumentTracker.CheckDirty(file); } } if (dirtyProjects != null) { foreach (SccProject project in dirtyProjects) { if (project.IsSolution) { provider.UpdateSolutionGlyph(); } else { project.NotifyGlyphChanged(); } } } if (maybeAdd != null) { using (SvnClient cl = GetService <ISvnClientPool>().GetNoUIClient()) { foreach (string file in maybeAdd) { SvnItem item = SvnCache[file]; // Only add // * files // * that are unversioned // * that are addable // * that are not ignored // * and just to be sure: that are still part of the solution if (item.IsFile && !item.IsVersioned && item.IsVersionable && !item.IsIgnored && item.InSolution && !item.IsSccExcluded) { SvnAddArgs aa = new SvnAddArgs(); aa.ThrowOnError = false; // Just ignore errors here; make the user add them themselves aa.AddParents = true; if (cl.Add(item.FullPath, aa)) { item.MarkDirty(); // Detect if we have a file that Subversion might detect as binary if (item.IsVersioned && !item.IsTextFile) { // Only check small files, avoid checking big binary files FileInfo fi = new FileInfo(item.FullPath); if (fi.Length < 10) { // We're sure it's at most 10 bytes here, so just read all byte[] fileBytes = File.ReadAllBytes(item.FullPath); // If the file starts with a UTF8 BOM, we're sure enough it's a text file, keep UTF16 & 32 binary if (StartsWith(fileBytes, new byte[] { 0xEF, 0xBB, 0xBF })) { // Delete the mime type property, so it's detected as a text file again SvnSetPropertyArgs pa = new SvnSetPropertyArgs(); pa.ThrowOnError = false; cl.DeleteProperty(item.FullPath, SvnPropertyNames.SvnMimeType, pa); } } } } } } } } }
public IEnumerable<Uri> GetRepositoryUris(bool forBrowse) { HybridCollection<Uri> uris = new HybridCollection<Uri>(); if (ProjectRootUri != null) uris.Add(ProjectRootUri); // Global keys (over all versions) using (RegistryKey rk = Config.OpenGlobalKey("Repositories")) { if (rk != null) LoadUris(uris, rk); } // Per hive using (RegistryKey rk = Config.OpenInstanceKey("Repositories")) { if (rk != null) LoadUris(uris, rk); } // Per user + Per hive using (RegistryKey rk = Config.OpenUserInstanceKey("Repositories")) { if (rk != null) LoadUris(uris, rk); } // Finally add the last used list from TortoiseSVN try { using (RegistryKey rk = Registry.CurrentUser.OpenSubKey( "SOFTWARE\\TortoiseSVN\\History\\repoURLS", RegistryKeyPermissionCheck.ReadSubTree)) { if (rk != null) LoadUris(uris, rk); } } catch (SecurityException) { /* Ignore no read only access; stupid sysadmins */ } IAnkhConfigurationService configSvc = Context.GetService<IAnkhConfigurationService>(); if (configSvc != null) { foreach (string u in configSvc.GetRecentReposUrls()) { Uri uri; if (u != null && Uri.TryCreate(u, UriKind.Absolute, out uri)) { if (!uris.Contains(uri)) uris.Add(uri); } } } return uris; }
public RuntimeTrackingProfile GetRuntimeTrackingProfile(TrackingProfile profile, Activity rootElement) { RuntimeTrackingProfile item = null; HybridCollection<RuntimeTrackingProfile> hybrids = null; lock (this.cache) { if (!this.cache.TryGetValue(rootElement, out hybrids)) { item = new RuntimeTrackingProfile(profile, rootElement); hybrids = new HybridCollection<RuntimeTrackingProfile>(); hybrids.Add(item); this.cache.Add(rootElement, hybrids); return item; } foreach (RuntimeTrackingProfile profile3 in hybrids.AsReadOnly()) { if ((string.CompareOrdinal(profile.Name, profile3.associatedProfile.Name) == 0) && (string.CompareOrdinal(profile.ActivityDefinitionId, profile3.associatedProfile.ActivityDefinitionId) == 0)) { item = profile3; break; } } if (item == null) { item = new RuntimeTrackingProfile(profile, rootElement); hybrids.Add(item); } } return item; }
public override void OnExecute(CommandEventArgs e) { List<GitItem> toRevert = new List<GitItem>(); HybridCollection<string> contained = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); HybridCollection<string> checkedItems = null; foreach (GitItem i in e.Selection.GetSelectedGitItems(false)) { if (contained.Contains(i.FullPath)) continue; contained.Add(i.FullPath); if (i.IsModified || (i.IsVersioned && i.IsDocumentDirty) || i.IsConflicted) toRevert.Add(i); } Predicate<GitItem> initialCheckedFilter = null; if (toRevert.Count > 0) { checkedItems = new HybridCollection<string>(contained, StringComparer.OrdinalIgnoreCase); initialCheckedFilter = delegate(GitItem item) { return checkedItems.Contains(item.FullPath); }; } foreach (GitItem i in e.Selection.GetSelectedGitItems(true)) { if (contained.Contains(i.FullPath)) continue; contained.Add(i.FullPath); if (i.IsModified || (i.IsVersioned && i.IsDocumentDirty)) toRevert.Add(i); } if (e.PromptUser || (!e.DontPrompt && !Shift)) { using (PendingChangeSelector pcs = new PendingChangeSelector()) { pcs.Text = CommandStrings.RevertDialogTitle; pcs.PreserveWindowPlacement = true; pcs.LoadItems(toRevert, null, initialCheckedFilter); if (pcs.ShowDialog(e.Context) != DialogResult.OK) return; toRevert.Clear(); toRevert.AddRange(pcs.GetSelectedItems()); } } IVisualGitOpenDocumentTracker documentTracker = e.GetService<IVisualGitOpenDocumentTracker>(); ICollection<string> revertPaths = GitItem.GetPaths(toRevert); documentTracker.SaveDocuments(revertPaths); // perform the actual revert using (DocumentLock dl = documentTracker.LockDocuments(revertPaths, DocumentLockType.NoReload)) using (dl.MonitorChangesForReload()) { e.GetService<IProgressRunner>().RunModal(CommandStrings.Reverting, delegate(object sender, ProgressWorkerArgs a) { GitRevertItemArgs ra = new GitRevertItemArgs(); ra.Depth = GitDepth.Empty; List<string> toRevertPaths = new List<string>(); foreach (GitItem item in toRevert) { toRevertPaths.Add(item.FullPath); } foreach (GitItem item in toRevert) { try { a.Client.RevertItem(toRevertPaths, ra); } catch (GitNoRepositoryException) { // Ignore path no repository exceptions. } } }); } }
bool PerformRevisionChanges(ILogControl log, CommandEventArgs e) { GitRevision startRevision = null; var startRevisionTime = DateTime.MaxValue; GitRevision endRevision = null; var endRevisionTime = DateTime.MinValue; int n = 0; HybridCollection<string> changedPaths = new HybridCollection<string>(); foreach (IGitLogItem item in e.Selection.GetSelection<IGitLogItem>()) { if (startRevisionTime > item.CommitDate) { startRevisionTime = item.CommitDate; startRevision = item.Revision; } if (endRevisionTime < item.CommitDate) { endRevisionTime = item.CommitDate; endRevision = item.Revision; } n++; } if (n > 0) { ExecuteDiff(e, log.Origins, new GitRevisionRange(n == 1 ? startRevision - 1 : startRevision, endRevision)); return true; } return false; }
/// <summary> /// Gets the SvnItem of the document file and all subdocument files (SccSpecial files) /// </summary> /// <param name="document">The document.</param> /// <returns></returns> internal IEnumerable<SvnItem> GetAllDocumentItems(string document) { if (string.IsNullOrEmpty(document)) throw new ArgumentNullException("document"); SvnItem item = StatusCache[document]; if (item == null) yield break; yield return item; SccProjectFile pf; if (_fileMap.TryGetValue(item.FullPath, out pf)) { HybridCollection<string> subFiles = null; if (pf.FirstReference != null) foreach (string path in pf.FirstReference.GetSubFiles()) { if (subFiles == null) { subFiles = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); subFiles.Add(item.FullPath); } if (subFiles.Contains(path)) continue; item = StatusCache[path]; if (item != null) yield return item; subFiles.Add(item.FullPath); } } }
/// <summary> /// Called by projects and editors before modifying a file /// The function allows the source control systems to take the necessary actions (checkout, flip attributes) /// to make the file writable in order to allow the edit to continue /// /// There are a lot of cases to deal with during QueryEdit/QuerySave. /// - called in commmand line mode, when UI cannot be displayed /// - called during builds, when save shoudn't probably be allowed /// - called during projects migration, when projects are not open and not registered yet with source control /// - checking out files may bring new versions from vss database which may be reloaded and the user may lose in-memory changes; some other files may not be reloadable /// - not all editors call QueryEdit when they modify the file the first time (buggy editors!), and the files may be already dirty in memory when QueryEdit is called /// - files on disk may be modified outside IDE and may have attributes incorrect for their scc status /// - checkouts may fail /// </summary> /// <param name="rgfQueryEdit">The RGF query edit.</param> /// <param name="cFiles">The c files.</param> /// <param name="rgpszMkDocuments">The RGPSZ mk documents.</param> /// <param name="rgrgf">The RGRGF.</param> /// <param name="rgFileInfo">The rg file info.</param> /// <param name="pfEditVerdict">The pf edit verdict.</param> /// <param name="prgfMoreInfo">The PRGF more info.</param> /// <returns></returns> public int QueryEditFiles(uint rgfQueryEdit, int cFiles, string[] rgpszMkDocuments, uint[] rgrgf, VSQEQS_FILE_ATTRIBUTE_DATA[] rgFileInfo, out uint pfEditVerdict, out uint prgfMoreInfo) { tagVSQueryEditFlags queryFlags = (tagVSQueryEditFlags)rgfQueryEdit; pfEditVerdict = (uint)tagVSQueryEditResult.QER_EditOK; prgfMoreInfo = (uint)(tagVSQueryEditResultFlags)0; // Must be 0 when verdict is QER_EditOK or you see failures like issue #624 bool allowUI = (queryFlags & (tagVSQueryEditFlags.QEF_SilentMode | tagVSQueryEditFlags.QEF_ReportOnly | tagVSQueryEditFlags.QEF_ForceEdit_NoPrompting)) == 0; bool?allowReadOnlyNonSccWrites = null; if (rgpszMkDocuments == null) { return(VSErr.E_POINTER); } try { // If the editor asks us to do anything in our power to make it editable // without prompting, just make those files writable. if ((queryFlags & tagVSQueryEditFlags.QEF_ForceEdit_NoPrompting) != 0) { return(QueryEditForceWritable(rgpszMkDocuments)); } HybridCollection <string> mustLockFiles = null; HybridCollection <string> readOnlyEditFiles = null; List <SvnItem> mustLockItems = null; List <SvnItem> readOnlyItems = null; for (int i = 0; i < cFiles; i++) { SvnItem item; { string file = rgpszMkDocuments[i]; if (!IsSafeSccPath(file)) { continue; // Skip non scc paths (Includes %TEMP%\*) } item = StatusCache[file]; } Monitor.ScheduleDirtyCheck(item); if (item.IsReadOnlyMustLock && !item.IsDirectory) { if (!allowUI) { pfEditVerdict = (uint)tagVSQueryEditResult.QER_EditNotOK; prgfMoreInfo = (uint)(tagVSQueryEditResultFlags.QER_ReadOnlyUnderScc | tagVSQueryEditResultFlags.QER_NoisyCheckoutRequired); return(VSErr.S_OK); } if (mustLockItems == null) { mustLockFiles = new HybridCollection <string>(StringComparer.OrdinalIgnoreCase); mustLockItems = new List <SvnItem>(); } if (!mustLockFiles.Contains(item.FullPath)) { mustLockFiles.Add(item.FullPath); mustLockItems.Add(item); } } else if (item.IsReadOnly) { if (!allowReadOnlyNonSccWrites.HasValue) { allowReadOnlyNonSccWrites = AllowReadOnlyNonSccWrites(); } if (!allowReadOnlyNonSccWrites.Value) { if (!allowUI) { pfEditVerdict = (uint)tagVSQueryEditResult.QER_EditNotOK; prgfMoreInfo = (uint)(tagVSQueryEditResultFlags.QER_InMemoryEditNotAllowed | tagVSQueryEditResultFlags.QER_ReadOnlyNotUnderScc | tagVSQueryEditResultFlags.QER_NoisyPromptRequired); return(VSErr.S_OK); } if (readOnlyEditFiles == null) { readOnlyEditFiles = new HybridCollection <string>(StringComparer.OrdinalIgnoreCase); readOnlyItems = new List <SvnItem>(); } if (!readOnlyEditFiles.Contains(item.FullPath)) { readOnlyEditFiles.Add(item.FullPath); readOnlyItems.Add(item); } } // else // allow editting } } if (mustLockItems != null) { List <SvnItem> mustBeLocked = new List <SvnItem>(mustLockItems); // Look at all subfiles of the must be locked document and add these to the dialog // to make it easier to lock them too foreach (string lockFile in new List <string>(mustLockFiles)) { foreach (string file in GetAllDocumentFiles(lockFile)) { if (!mustLockFiles.Contains(file)) { mustLockFiles.Add(file); mustLockItems.Add(StatusCache[file]); } } } CommandService.DirectlyExecCommand(AnkhCommand.SccLock, mustLockItems, CommandPrompt.DoDefault); // Only check the original list; the rest of the items in mustLockItems is optional foreach (SvnItem i in mustBeLocked) { if (i.IsReadOnlyMustLock) { // User has probably canceled the lock operation, or it failed. pfEditVerdict = (uint)tagVSQueryEditResult.QER_EditNotOK; prgfMoreInfo = (uint)(tagVSQueryEditResultFlags.QER_CheckoutCanceledOrFailed | tagVSQueryEditResultFlags.QER_ReadOnlyUnderScc); break; } } } if (readOnlyItems != null) { // TODO: Handle multiple items correctly // Is this only for non-scc items or also for scc items that are readonly for other reasons? CommandResult result = CommandService.DirectlyExecCommand(AnkhCommand.MakeNonSccFileWriteable, readOnlyItems[0], CommandPrompt.DoDefault); bool allowed = result.Result is bool?(bool)result.Result : false; if (!allowed) { pfEditVerdict = (uint)tagVSQueryEditResult.QER_EditNotOK; prgfMoreInfo = (uint)(tagVSQueryEditResultFlags.QER_InMemoryEditNotAllowed | tagVSQueryEditResultFlags.QER_ReadOnlyNotUnderScc // TODO: Specialize to SCC? ); } } } catch (Exception ex) { IAnkhErrorHandler eh = GetService <IAnkhErrorHandler>(); if (eh != null && eh.IsEnabled(ex)) { eh.OnError(ex); } else { throw; } } return(VSErr.S_OK); }
private static void PerformUpdate(CommandEventArgs e, ProgressWorkerArgs wa, SvnRevision rev, bool allowUnversionedObstructions, bool updateExternals, bool setDepthInfinity, IEnumerable<List<string>> groups, out SvnUpdateResult updateResult) { SvnUpdateArgs ua = new SvnUpdateArgs(); ua.Revision = rev; ua.AllowObstructions = allowUnversionedObstructions; ua.IgnoreExternals = !updateExternals; ua.KeepDepth = setDepthInfinity; updateResult = null; HybridCollection<string> handledExternals = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); ua.Notify += delegate(object ss, SvnNotifyEventArgs ee) { if (ee.Action == SvnNotifyAction.UpdateExternal) { if (!handledExternals.Contains(ee.FullPath)) handledExternals.Add(ee.FullPath); } }; e.Context.GetService<IConflictHandler>().RegisterConflictHandler(ua, wa.Synchronizer); foreach (List<string> group in groups) { // Currently Subversion runs update per item passed and in // Subversion 1.6 passing each item separately is actually // a tiny bit faster than passing them all at once. // (sleep_for_timestamp fails its fast route) foreach (string path in group) { if (handledExternals.Contains(path)) continue; SvnUpdateResult result; wa.Client.Update(path, ua, out result); if (updateResult == null) updateResult = result; // Return the primary update as version for output } } }
public RuntimeTrackingProfile GetRuntimeTrackingProfile(TrackingProfile profile, Activity rootElement) { Fx.Assert(rootElement != null, "Root element must be valid"); RuntimeTrackingProfile foundRuntimeProfile = null; HybridCollection<RuntimeTrackingProfile> runtimeProfileList = null; lock (this.cache) { if (!this.cache.TryGetValue(rootElement, out runtimeProfileList)) { foundRuntimeProfile = new RuntimeTrackingProfile(profile, rootElement); runtimeProfileList = new HybridCollection<RuntimeTrackingProfile>(); runtimeProfileList.Add(foundRuntimeProfile); this.cache.Add(rootElement, runtimeProfileList); } else { ReadOnlyCollection<RuntimeTrackingProfile> runtimeProfileCollection = runtimeProfileList.AsReadOnly(); foreach (RuntimeTrackingProfile runtimeProfile in runtimeProfileCollection) { if (string.CompareOrdinal(profile.Name, runtimeProfile.associatedProfile.Name) == 0 && string.CompareOrdinal(profile.ActivityDefinitionId, runtimeProfile.associatedProfile.ActivityDefinitionId) == 0) { foundRuntimeProfile = runtimeProfile; break; } } if (foundRuntimeProfile == null) { foundRuntimeProfile = new RuntimeTrackingProfile(profile, rootElement); runtimeProfileList.Add(foundRuntimeProfile); } } } return foundRuntimeProfile; }
public override void OnExecute(CommandEventArgs e) { if (e.Argument != null) { ShowUpdate(e); return; } int interval = 24 * 6; // 6 days IAnkhConfigurationService config = e.GetService<IAnkhConfigurationService>(); if (config.Instance.DisableUpdateCheck) return; using (RegistryKey rk = config.OpenUserInstanceKey("UpdateCheck")) { object value = rk.GetValue("Interval"); if (value is int) { interval = (int)value; if (interval <= 0) return; } } Version version = GetCurrentVersion(e.Context); Version vsVersion = e.GetService<IAnkhSolutionSettings>().VisualStudioVersion; Version osVersion = Environment.OSVersion.Version; StringBuilder sb = new StringBuilder(); sb.Append("http://svc.ankhsvn.net/svc/"); if (IsDevVersion()) sb.Append("dev/"); sb.Append("update-info/"); sb.Append(version.ToString(2)); sb.Append(".xml"); sb.Append("?av="); sb.Append(version); sb.Append("&vs="); sb.Append(vsVersion); sb.Append("&os="); sb.Append(osVersion); if (IsDevVersion()) sb.Append("&dev=1"); sb.AppendFormat(CultureInfo.InvariantCulture, "&iv={0}", interval); int x = 0; // Create some hashcode that is probably constant and unique for all users // using the same IP address, but not translatable to a single user try { foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces()) { string type = ni.NetworkInterfaceType.ToString(); if (type.Contains("Ethernet") || type.Contains("Wireless")) x ^= ni.GetPhysicalAddress().GetHashCode(); } } catch { } sb.AppendFormat(CultureInfo.InvariantCulture, "&xx={0}&pc={1}", x, Environment.ProcessorCount); try { using (RegistryKey rk = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP")) { if (rk != null) { sb.Append("&dn="); Regex re = new Regex("^[vV]([0-9]+\\.[0-9]+)(\\.[0-9]+)*", RegexOptions.Singleline); bool first = true; HybridCollection<string> vers = new HybridCollection<string>(); foreach (string s in rk.GetSubKeyNames()) { Match m = re.Match(s); if (m.Success) { string v = m.Groups[1].Value; if (vers.Contains(v)) continue; vers.Add(v); if (first) first = false; else sb.Append(','); sb.Append(v); } } } } } catch { } Uri updateUri = new Uri(sb.ToString()); WebRequest wr = WebRequest.Create(updateUri); HttpWebRequest hwr = wr as HttpWebRequest; if (hwr != null) { hwr.AllowAutoRedirect = true; hwr.AllowWriteStreamBuffering = true; hwr.UserAgent = string.Format("AnkhSVN/{0} VisualStudio/{1} Windows/{2}", version, vsVersion, osVersion); } wr.BeginGetResponse(OnResponse, wr); }
void AddActivitySubscription(ActivityStateQuery query) { this.trackingRecordPreFilter.TrackActivityStateRecords = true; foreach (string state in query.States) { if (string.CompareOrdinal(state, "*") == 0) { this.trackingRecordPreFilter.TrackActivityStateRecordsClosedState = true; this.trackingRecordPreFilter.TrackActivityStateRecordsExecutingState = true; break; } if (string.CompareOrdinal(state, ActivityStates.Closed) == 0) { this.trackingRecordPreFilter.TrackActivityStateRecordsClosedState = true; } else if (string.CompareOrdinal(state, ActivityStates.Executing) == 0) { this.trackingRecordPreFilter.TrackActivityStateRecordsExecutingState = true; } } if (this.activitySubscriptions == null) { this.activitySubscriptions = new Dictionary<string, HybridCollection<ActivityStateQuery>>(); } HybridCollection<ActivityStateQuery> subscription; if (!this.activitySubscriptions.TryGetValue(query.ActivityName, out subscription)) { subscription = new HybridCollection<ActivityStateQuery>(); this.activitySubscriptions[query.ActivityName] = subscription; } subscription.Add((ActivityStateQuery)query); AddActivityName(query.ActivityName); }
/// <see cref="VisualGit.Commands.ICommandHandler.OnExecute" /> public void OnExecute(CommandEventArgs e) { List<GitItem> gitItems = new List<GitItem>(); IFileStatusCache cache = e.GetService<IFileStatusCache>(); GitRevision revision = null; string repositoryPath = null; switch (e.Command) { case VisualGitCommand.LogMergeThisRevision: ILogControl logWindow = e.Selection.GetActiveControl<ILogControl>(); IProgressRunner progressRunner = e.GetService<IProgressRunner>(); if (logWindow == null) return; IGitLogItem logItem = EnumTools.GetSingle(e.Selection.GetSelection<IGitLogItem>()); if (logItem == null) return; revision = logItem.Revision; repositoryPath = logItem.RepositoryRoot; break; case VisualGitCommand.ItemMerge: // TODO: Check for solution and/or project selection to use the folder instead of the file foreach (GitItem item in e.Selection.GetSelectedGitItems(false)) { gitItems.Add(item); } break; case VisualGitCommand.ProjectMerge: foreach (GitProject p in e.Selection.GetSelectedProjects(false)) { IProjectFileMapper pfm = e.GetService<IProjectFileMapper>(); IGitProjectInfo info = pfm.GetProjectInfo(p); if (info != null && info.ProjectDirectory != null) { gitItems.Add(cache[info.ProjectDirectory]); } } break; case VisualGitCommand.SolutionMerge: gitItems.Add(cache[e.GetService<IVisualGitSolutionSettings>().ProjectRoot]); break; default: throw new InvalidOperationException(); } if (repositoryPath == null) { Debug.Assert(gitItems.Count > 0); repositoryPath = GitTools.GetRepositoryRoot(gitItems[0].FullPath); } GitRef mergeBranch; var args = new GitMergeArgs(); using (var dialog = new MergeDialog()) { dialog.Context = e.Context; dialog.Revision = revision; dialog.RepositoryPath = repositoryPath; if (gitItems.Count > 0) dialog.GitItem = gitItems[0]; dialog.Args = args; if (dialog.ShowDialog(e.Context) != DialogResult.OK) return; mergeBranch = dialog.MergeBranch; } // Get a list of all documents below the specified paths that are open in editors inside VS HybridCollection<string> lockPaths = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); IVisualGitOpenDocumentTracker documentTracker = e.GetService<IVisualGitOpenDocumentTracker>(); foreach (string file in documentTracker.GetDocumentsBelow(repositoryPath)) { if (!lockPaths.Contains(file)) lockPaths.Add(file); } documentTracker.SaveDocuments(lockPaths); // Make sure all files are saved before merging! using (DocumentLock lck = documentTracker.LockDocuments(lockPaths, DocumentLockType.NoReload)) using (lck.MonitorChangesForReload()) { GitException exception = null; e.GetService<IProgressRunner>().RunModal( "Changing Current Branch", delegate(object sender, ProgressWorkerArgs a) { e.GetService<IConflictHandler>().RegisterConflictHandler(args, a.Synchronizer); try { a.Client.Merge(repositoryPath, mergeBranch, args); } catch (GitException ex) { exception = ex; } }); if (exception != null) { e.GetService<IVisualGitErrorHandler>().OnWarning(exception); } } }
static void LoadUris(HybridCollection<Uri> uris, RegistryKey rk) { foreach (string name in rk.GetValueNames()) { string value = rk.GetValue(name) as string; if (value != null && !value.EndsWith("/")) value += "/"; Uri uri; if (value != null && Uri.TryCreate(value, UriKind.Absolute, out uri)) { if (!uris.Contains(uri)) uris.Add(uri); } } }
public override void OnExecute(CommandEventArgs e) { GitItem theItem = null; string path; GitRef currentBranch = null; string projectRoot = e.GetService<IVisualGitSolutionSettings>().ProjectRoot; if (e.Command == VisualGitCommand.SolutionSwitchDialog) path = projectRoot; else if (e.Command == VisualGitCommand.SwitchProject) { IProjectFileMapper mapper = e.GetService<IProjectFileMapper>(); path = null; foreach (GitProject item in e.Selection.GetSelectedProjects(true)) { IGitProjectInfo pi = mapper.GetProjectInfo(item); if (pi == null) continue; path = pi.ProjectDirectory; break; } if (string.IsNullOrEmpty(path)) return; } else if (e.Command == VisualGitCommand.LogSwitchToRevision) { IGitLogItem item = EnumTools.GetSingle(e.Selection.GetSelection<IGitLogItem>()); if (item == null) return; path = item.RepositoryRoot; currentBranch = new GitRef(item.Revision); } else { foreach (GitItem item in e.Selection.GetSelectedGitItems(false)) { if (item.IsVersioned) { theItem = item; break; } return; } path = theItem.FullPath; } IFileStatusCache statusCache = e.GetService<IFileStatusCache>(); GitItem pathItem = statusCache[path]; if (currentBranch == null) { using (var client = e.GetService<IGitClientPool>().GetNoUIClient()) { currentBranch = client.GetCurrentBranch(pathItem.FullPath); } if (currentBranch == null) return; // Should never happen on a real workingcopy } GitRef target; bool force = false; if (e.Argument is string) { target = new GitRef((string)e.Argument); } else using (SwitchDialog dlg = new SwitchDialog()) { dlg.GitOrigin = new GitOrigin(pathItem); dlg.Context = e.Context; dlg.LocalPath = GitTools.GetRepositoryRoot(path); dlg.SwitchToBranch = currentBranch; if (dlg.ShowDialog(e.Context) != DialogResult.OK) return; target = dlg.SwitchToBranch; force = dlg.Force; } // Get a list of all documents below the specified paths that are open in editors inside VS HybridCollection<string> lockPaths = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); IVisualGitOpenDocumentTracker documentTracker = e.GetService<IVisualGitOpenDocumentTracker>(); foreach (string file in documentTracker.GetDocumentsBelow(path)) { if (!lockPaths.Contains(file)) lockPaths.Add(file); } documentTracker.SaveDocuments(lockPaths); // Make sure all files are saved before merging! using (DocumentLock lck = documentTracker.LockDocuments(lockPaths, DocumentLockType.NoReload)) using (lck.MonitorChangesForReload()) { GitSwitchArgs args = new GitSwitchArgs(); GitException exception = null; e.GetService<IProgressRunner>().RunModal( "Changing Current Branch", delegate(object sender, ProgressWorkerArgs a) { args.Force = force; // TODO: Decide whether it is necessary for the switch // command to report conflicts. #if NOT_IMPLEMENTED e.GetService<IConflictHandler>().RegisterConflictHandler(args, a.Synchronizer); #endif try { a.Client.Switch(path, target, args); } catch (GitException ex) { exception = ex; } }); if (exception != null) { e.GetService<IVisualGitErrorHandler>().OnWarning(exception); } } }
public override void OnExecute(CommandEventArgs e) { IAnkhServiceEvents ci = e.GetService <IAnkhServiceEvents>(); if (ci != null) { ci.OnLastChanged(new LastChangedEventArgs(null, null)); } SvnRevision rev; bool allowUnversionedObstructions = false; bool updateExternals = true; bool setDepthInfinity = true; IAnkhSolutionSettings settings = e.GetService <IAnkhSolutionSettings>(); ISvnStatusCache cache = e.GetService <ISvnStatusCache>(); IProjectFileMapper mapper = e.GetService <IProjectFileMapper>(); Uri reposRoot = null; if (IsHeadCommand(e.Command) || e.DontPrompt) { rev = SvnRevision.Head; } else if (IsSolutionCommand(e.Command)) { SvnItem projectItem = settings.ProjectRootSvnItem; Debug.Assert(projectItem != null, "Has item"); using (UpdateDialog ud = new UpdateDialog()) { ud.ItemToUpdate = projectItem; ud.Revision = SvnRevision.Head; if (ud.ShowDialog(e.Context) != DialogResult.OK) { return; } rev = ud.Revision; allowUnversionedObstructions = ud.AllowUnversionedObstructions; updateExternals = ud.UpdateExternals; setDepthInfinity = ud.SetDepthInfinty; } } else if (IsFolderCommand(e.Command)) { SvnItem dirItem = EnumTools.GetFirst(e.Selection.GetSelectedSvnItems(false)); Debug.Assert(dirItem != null && dirItem.IsDirectory && dirItem.IsVersioned); using (UpdateDialog ud = new UpdateDialog()) { ud.Text = CommandStrings.UpdateFolder; ud.FolderLabelText = CommandStrings.UpdateFolderLabel; ud.ItemToUpdate = dirItem; ud.Revision = SvnRevision.Head; if (ud.ShowDialog(e.Context) != DialogResult.OK) { return; } rev = ud.Revision; allowUnversionedObstructions = ud.AllowUnversionedObstructions; updateExternals = ud.UpdateExternals; setDepthInfinity = ud.SetDepthInfinty; } } else { // We checked there was only a single repository to select a revision // from in OnUpdate, so we can suffice with only calculate the path SvnItem si = null; SvnOrigin origin = null; foreach (SccProject p in GetSelectedProjects(e)) { ISccProjectInfo pi = mapper.GetProjectInfo(p); if (pi == null || pi.ProjectDirectory == null) { continue; } SvnItem item = cache[pi.ProjectDirectory]; if (!item.IsVersioned) { continue; } if (si == null && origin == null) { si = item; origin = new SvnOrigin(item); reposRoot = item.WorkingCopy.RepositoryRoot; } else { si = null; string urlPath1 = origin.Uri.AbsolutePath; string urlPath2 = item.Uri.AbsolutePath; int i = 0; while (i < urlPath1.Length && i < urlPath2.Length && urlPath1[i] == urlPath2[i]) { i++; } while (i > 0 && urlPath1[i - 1] != '/') { i--; } origin = new SvnOrigin(new Uri(origin.Uri, urlPath1.Substring(0, i)), origin.RepositoryRoot); } } Debug.Assert(origin != null); using (UpdateDialog ud = new UpdateDialog()) { ud.Text = CommandStrings.UpdateProject; if (si != null) { ud.ItemToUpdate = si; } else { ud.SvnOrigin = origin; ud.SetMultiple(true); } ud.Revision = SvnRevision.Head; if (ud.ShowDialog(e.Context) != DialogResult.OK) { return; } rev = ud.Revision; allowUnversionedObstructions = ud.AllowUnversionedObstructions; updateExternals = ud.UpdateExternals; setDepthInfinity = ud.SetDepthInfinty; } } Dictionary <string, SvnItem> itemsToUpdate = new Dictionary <string, SvnItem>(StringComparer.OrdinalIgnoreCase); SortedList <string, UpdateGroup> groups = new SortedList <string, UpdateGroup>(StringComparer.OrdinalIgnoreCase); // Get a list of all documents below the specified paths that are open in editors inside VS HybridCollection <string> lockPaths = new HybridCollection <string>(StringComparer.OrdinalIgnoreCase); IAnkhOpenDocumentTracker documentTracker = e.GetService <IAnkhOpenDocumentTracker>(); foreach (SvnItem item in GetAllUpdateRoots(e)) { // GetAllUpdateRoots can (and probably will) return duplicates! if (itemsToUpdate.ContainsKey(item.FullPath) || !item.IsVersioned) { continue; } SvnWorkingCopy wc = item.WorkingCopy; if (!IsHeadCommand(e.Command) && reposRoot != null) { // Specific revisions are only valid on a single repository! if (wc != null && wc.RepositoryRoot != reposRoot) { continue; } } UpdateGroup group; if (!groups.TryGetValue(wc.FullPath, out group)) { group = new UpdateGroup(wc.FullPath); groups.Add(wc.FullPath, group); } group.Nodes.Add(item.FullPath); itemsToUpdate.Add(item.FullPath, item); foreach (string file in documentTracker.GetDocumentsBelow(item.FullPath)) { if (!lockPaths.Contains(file)) { lockPaths.Add(file); } } } documentTracker.SaveDocuments(lockPaths); // Make sure all files are saved before updating/merging! using (DocumentLock lck = documentTracker.LockDocuments(lockPaths, DocumentLockType.NoReload)) using (lck.MonitorChangesForReload()) { SvnUpdateResult updateResult = null; ProgressRunnerArgs pa = new ProgressRunnerArgs(); pa.CreateLog = true; string title; if (IsSolutionCommand(e.Command)) { title = CommandStrings.UpdatingSolution; } else if (IsFolderCommand(e.Command)) { title = CommandStrings.UpdatingFolder; } else { title = CommandStrings.UpdatingProject; } e.GetService <IProgressRunner>().RunModal(title, pa, delegate(object sender, ProgressWorkerArgs a) { PerformUpdate(e, a, rev, allowUnversionedObstructions, updateExternals, setDepthInfinity, groups.Values, out updateResult); }); if (ci != null && updateResult != null && IsSolutionCommand(e.Command)) { ci.OnLastChanged(new LastChangedEventArgs(CommandStrings.UpdatedToTitle, updateResult.Revision.ToString())); } } }
static bool CheckoutWorkingCopyForSolution(CommandEventArgs e, ref bool confirmed) { using (SvnClient cl = e.GetService <ISvnClientPool>().GetClient()) using (AddToSubversion dialog = new AddToSubversion()) { dialog.PathToAdd = e.Selection.SolutionFilename; if (e.Argument is IAnkhSccService) { dialog.CommitAllVisible = false; dialog.CommitAllFiles = false; } else { dialog.CommitAllFiles = true; } if (dialog.ShowDialog(e.Context) != DialogResult.OK) { return(false); // Don't set as managed by AnkhSVN } confirmed = true; if (dialog.CommitAllFiles) { HybridCollection <string> allFiles = new HybridCollection <string>(StringComparer.OrdinalIgnoreCase); string logMessage; string wcPath = dialog.WorkingCopyDir; Uri reposUrl = dialog.RepositoryAddUrl; allFiles.UniqueAddRange(e.GetService <IProjectFileMapper>().GetAllFilesOfAllProjects(true)); using (CreateDirectoryDialog dlg = new CreateDirectoryDialog()) { dlg.Text = CommandStrings.ImportingTitle; dlg.NewDirectoryName = dialog.RepositoryAddUrl.ToString(); dlg.NewDirectoryReadonly = true; if (dlg.ShowDialog(e.Context) != DialogResult.OK) { return(false); } logMessage = dlg.LogMessage; } IAnkhOpenDocumentTracker documentTracker = e.GetService <IAnkhOpenDocumentTracker>(); documentTracker.SaveDocuments(allFiles); // Make sure all files are saved before updating/merging! using (DocumentLock lck = documentTracker.LockDocuments(allFiles, DocumentLockType.NoReload)) using (lck.MonitorChangesForReload()) { e.GetService <IProgressRunner>().RunModal(CommandStrings.ImportingTitle, delegate(object sender, ProgressWorkerArgs a) { SvnImportArgs importArgs = new SvnImportArgs(); importArgs.LogMessage = logMessage; importArgs.Filter += delegate(object ieSender, SvnImportFilterEventArgs ie) { if (ie.NodeKind != SvnNodeKind.Directory) { ie.Filter = !allFiles.Contains(ie.FullPath); } else { bool filter = true; foreach (string p in allFiles) { if (SvnItem.IsBelowRoot(p, ie.FullPath)) { filter = false; break; } } if (filter) { ie.Filter = true; } } }; a.Client.Import(wcPath, reposUrl, importArgs); }); } } else { Collection <SvnInfoEventArgs> info; SvnInfoArgs ia = new SvnInfoArgs(); ia.ThrowOnError = false; if (!cl.GetInfo(dialog.RepositoryAddUrl, ia, out info)) { // Target uri doesn't exist in the repository, let's create if (!RemoteCreateDirectory(e, dialog.Text, dialog.RepositoryAddUrl, cl)) { return(false); // Create failed; bail out } } // Create working copy SvnCheckOutArgs coArg = new SvnCheckOutArgs(); coArg.AllowObstructions = true; cl.CheckOut(dialog.RepositoryAddUrl, dialog.WorkingCopyDir, coArg); // Add solutionfile so we can set properties (set managed) AddPathToSubversion(e, e.Selection.SolutionFilename); IAnkhSolutionSettings settings = e.GetService <IAnkhSolutionSettings>(); IProjectFileMapper mapper = e.GetService <IProjectFileMapper>(); IFileStatusMonitor monitor = e.GetService <IFileStatusMonitor>(); settings.ProjectRoot = SvnTools.GetNormalizedFullPath(dialog.WorkingCopyDir); if (monitor != null && mapper != null) { // Make sure all visible glyphs are updated to reflect a new working copy monitor.ScheduleSvnStatus(mapper.GetAllFilesOfAllProjects()); } } return(true); } }
void OnPendingChangesListFlushed(object sender, PendingChangeEventArgs e) { if (_listItems.Count > 0) { _checkedItems = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); foreach (PendingCommitItem pci in _listItems.Values) { if (pci.Checked && !_checkedItems.Contains(pci.FullPath)) _checkedItems.Add(pci.FullPath); } _listItems.Clear(); pendingCommits.ClearItems(); } }
/// <summary> /// Called by projects and editors before modifying a file /// The function allows the source control systems to take the necessary actions (checkout, flip attributes) /// to make the file writable in order to allow the edit to continue /// /// There are a lot of cases to deal with during QueryEdit/QuerySave. /// - called in commmand line mode, when UI cannot be displayed /// - called during builds, when save shoudn't probably be allowed /// - called during projects migration, when projects are not open and not registered yet with source control /// - checking out files may bring new versions from vss database which may be reloaded and the user may lose in-memory changes; some other files may not be reloadable /// - not all editors call QueryEdit when they modify the file the first time (buggy editors!), and the files may be already dirty in memory when QueryEdit is called /// - files on disk may be modified outside IDE and may have attributes incorrect for their scc status /// - checkouts may fail /// </summary> /// <param name="rgfQueryEdit">The RGF query edit.</param> /// <param name="cFiles">The c files.</param> /// <param name="rgpszMkDocuments">The RGPSZ mk documents.</param> /// <param name="rgrgf">The RGRGF.</param> /// <param name="rgFileInfo">The rg file info.</param> /// <param name="pfEditVerdict">The pf edit verdict.</param> /// <param name="prgfMoreInfo">The PRGF more info.</param> /// <returns></returns> public int QueryEditFiles(uint rgfQueryEdit, int cFiles, string[] rgpszMkDocuments, uint[] rgrgf, VSQEQS_FILE_ATTRIBUTE_DATA[] rgFileInfo, out uint pfEditVerdict, out uint prgfMoreInfo) { tagVSQueryEditFlags queryFlags = (tagVSQueryEditFlags)rgfQueryEdit; pfEditVerdict = (uint)tagVSQueryEditResult.QER_EditOK; prgfMoreInfo = (uint)(tagVSQueryEditResultFlags)0; // Must be 0 when verdict is QER_EditOK or you see failures like issue #624 bool allowUI = (queryFlags & (tagVSQueryEditFlags.QEF_SilentMode | tagVSQueryEditFlags.QEF_ReportOnly | tagVSQueryEditFlags.QEF_ForceEdit_NoPrompting)) == 0; bool? allowReadOnlyNonSccWrites = null; if (rgpszMkDocuments == null) return VSConstants.E_POINTER; try { // If the editor asks us to do anything in our power to make it editable // without prompting, just make those files writable. if ((queryFlags & tagVSQueryEditFlags.QEF_ForceEdit_NoPrompting) != 0) return QueryEditForceWritable(rgpszMkDocuments); HybridCollection<string> readOnlyEditFiles = null; List<GitItem> readOnlyItems = null; for (int i = 0; i < cFiles; i++) { string file = rgpszMkDocuments[i]; if (!IsSafeSccPath(file)) continue; // Skip non scc paths (Includes %TEMP%\*) file = GitTools.GetNormalizedFullPath(file); Monitor.ScheduleDirtyCheck(file); GitItem item = StatusCache[file]; if (item.IsReadOnly) { if (!allowReadOnlyNonSccWrites.HasValue) allowReadOnlyNonSccWrites = AllowReadOnlyNonSccWrites(); if (!allowReadOnlyNonSccWrites.Value) { if (!allowUI) { pfEditVerdict = (uint)tagVSQueryEditResult.QER_EditNotOK; prgfMoreInfo = (uint)(tagVSQueryEditResultFlags.QER_InMemoryEditNotAllowed | tagVSQueryEditResultFlags.QER_ReadOnlyNotUnderScc | tagVSQueryEditResultFlags.QER_NoisyPromptRequired); return VSConstants.S_OK; } if (readOnlyEditFiles == null) { readOnlyEditFiles = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); readOnlyItems = new List<GitItem>(); } if (!readOnlyEditFiles.Contains(item.FullPath)) { readOnlyEditFiles.Add(item.FullPath); readOnlyItems.Add(item); } } // else // allow editting } } if (readOnlyItems != null) { // TODO: Handle multiple items correctly // Is this only for non-scc items or also for scc items that are readonly for other reasons? CommandResult result = CommandService.DirectlyExecCommand(VisualGitCommand.MakeNonSccFileWriteable, readOnlyItems[0], CommandPrompt.DoDefault); bool allowed = result.Result is bool ? (bool)result.Result : false; if (!allowed) { pfEditVerdict = (uint)tagVSQueryEditResult.QER_EditNotOK; prgfMoreInfo = (uint)(tagVSQueryEditResultFlags.QER_InMemoryEditNotAllowed | tagVSQueryEditResultFlags.QER_ReadOnlyNotUnderScc // TODO: Specialize to SCC? ); } } } catch (Exception ex) { IVisualGitErrorHandler eh = GetService<IVisualGitErrorHandler>(); if (eh != null && eh.IsEnabled(ex)) eh.OnError(ex); else throw; } return VSConstants.S_OK; }
void PerformInitialUpdate(IPendingChangesManager manager) { if (manager == null) throw new ArgumentNullException("manager"); pendingCommits.BeginUpdate(); _listItems.Clear(); // Make sure we are clear pendingCommits.ClearItems(); try { foreach (PendingChange pc in manager.GetAll()) { PendingCommitItem pi = new PendingCommitItem(pendingCommits, pc); _listItems.Add(pc.FullPath, pi); if (_checkedItems != null) pi.Checked = _checkedItems.Contains(pc.FullPath); pendingCommits.Items.Add(pi); } _checkedItems = null; } finally { pendingCommits.EndUpdate(); pendingCommits.Invalidate(); } }
/// <summary> /// Called by projects and editors before modifying a file /// The function allows the source control systems to take the necessary actions (checkout, flip attributes) /// to make the file writable in order to allow the edit to continue /// /// There are a lot of cases to deal with during QueryEdit/QuerySave. /// - called in commmand line mode, when UI cannot be displayed /// - called during builds, when save shoudn't probably be allowed /// - called during projects migration, when projects are not open and not registered yet with source control /// - checking out files may bring new versions from vss database which may be reloaded and the user may lose in-memory changes; some other files may not be reloadable /// - not all editors call QueryEdit when they modify the file the first time (buggy editors!), and the files may be already dirty in memory when QueryEdit is called /// - files on disk may be modified outside IDE and may have attributes incorrect for their scc status /// - checkouts may fail /// </summary> /// <param name="rgfQueryEdit">The RGF query edit.</param> /// <param name="cFiles">The c files.</param> /// <param name="rgpszMkDocuments">The RGPSZ mk documents.</param> /// <param name="rgrgf">The RGRGF.</param> /// <param name="rgFileInfo">The rg file info.</param> /// <param name="pfEditVerdict">The pf edit verdict.</param> /// <param name="prgfMoreInfo">The PRGF more info.</param> /// <returns></returns> public int QueryEditFiles(uint rgfQueryEdit, int cFiles, string[] rgpszMkDocuments, uint[] rgrgf, VSQEQS_FILE_ATTRIBUTE_DATA[] rgFileInfo, out uint pfEditVerdict, out uint prgfMoreInfo) { tagVSQueryEditFlags queryFlags = (tagVSQueryEditFlags)rgfQueryEdit; pfEditVerdict = (uint)tagVSQueryEditResult.QER_EditOK; prgfMoreInfo = (uint)(tagVSQueryEditResultFlags)0; // Must be 0 when verdict is QER_EditOK or you see failures like issue #624 bool allowUI = (queryFlags & (tagVSQueryEditFlags.QEF_SilentMode | tagVSQueryEditFlags.QEF_ReportOnly | tagVSQueryEditFlags.QEF_ForceEdit_NoPrompting)) == 0; bool? allowReadOnlyNonSccWrites = null; if (rgpszMkDocuments == null) return VSConstants.E_POINTER; try { // If the editor asks us to do anything in our power to make it editable // without prompting, just make those files writable. if ((queryFlags & tagVSQueryEditFlags.QEF_ForceEdit_NoPrompting) != 0) return QueryEditForceWritable(rgpszMkDocuments); HybridCollection<string> mustLockFiles = null; HybridCollection<string> readOnlyEditFiles = null; List<SvnItem> mustLockItems = null; List<SvnItem> readOnlyItems = null; for (int i = 0; i < cFiles; i++) { string file = rgpszMkDocuments[i]; if (!IsSafeSccPath(file)) continue; // Skip non scc paths (Includes %TEMP%\*) file = SvnTools.GetNormalizedFullPath(file); Monitor.ScheduleDirtyCheck(file); SvnItem item = StatusCache[file]; if (item.IsReadOnlyMustLock && !item.IsDirectory) { if (!allowUI) { pfEditVerdict = (uint)tagVSQueryEditResult.QER_EditNotOK; prgfMoreInfo = (uint)(tagVSQueryEditResultFlags.QER_ReadOnlyUnderScc | tagVSQueryEditResultFlags.QER_NoisyCheckoutRequired); return VSConstants.S_OK; } if (mustLockItems == null) { mustLockFiles = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); mustLockItems = new List<SvnItem>(); } if (!mustLockFiles.Contains(item.FullPath)) { mustLockFiles.Add(item.FullPath); mustLockItems.Add(item); } } else if (item.IsReadOnly) { if (!allowReadOnlyNonSccWrites.HasValue) allowReadOnlyNonSccWrites = AllowReadOnlyNonSccWrites(); if (!allowReadOnlyNonSccWrites.Value) { if (!allowUI) { pfEditVerdict = (uint)tagVSQueryEditResult.QER_EditNotOK; prgfMoreInfo = (uint)(tagVSQueryEditResultFlags.QER_InMemoryEditNotAllowed | tagVSQueryEditResultFlags.QER_ReadOnlyNotUnderScc | tagVSQueryEditResultFlags.QER_NoisyPromptRequired); return VSConstants.S_OK; } if (readOnlyEditFiles == null) { readOnlyEditFiles = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); readOnlyItems = new List<SvnItem>(); } if (!readOnlyEditFiles.Contains(item.FullPath)) { readOnlyEditFiles.Add(item.FullPath); readOnlyItems.Add(item); } } // else // allow editting } } if (mustLockItems != null) { List<SvnItem> mustBeLocked = new List<SvnItem>(mustLockItems); // Look at all subfiles of the must be locked document and add these to the dialog // to make it easier to lock them too foreach (string lockFile in new List<string>(mustLockFiles)) { foreach (SvnItem item in GetAllDocumentItems(lockFile)) { if (!mustLockFiles.Contains(item.FullPath)) { mustLockFiles.Add(item.FullPath); mustLockItems.Add(item); } } } CommandService.DirectlyExecCommand(AnkhCommand.SccLock, mustLockItems, CommandPrompt.DoDefault); // Only check the original list; the rest of the items in mustLockItems is optional foreach (SvnItem i in mustBeLocked) { if (i.IsReadOnlyMustLock) { // User has probably canceled the lock operation, or it failed. pfEditVerdict = (uint)tagVSQueryEditResult.QER_EditNotOK; prgfMoreInfo = (uint)(tagVSQueryEditResultFlags.QER_CheckoutCanceledOrFailed | tagVSQueryEditResultFlags.QER_ReadOnlyUnderScc); break; } } } if (readOnlyItems != null) { // TODO: Handle multiple items correctly // Is this only for non-scc items or also for scc items that are readonly for other reasons? CommandResult result = CommandService.DirectlyExecCommand(AnkhCommand.MakeNonSccFileWriteable, readOnlyItems[0], CommandPrompt.DoDefault); bool allowed = result.Result is bool ? (bool)result.Result : false; if (!allowed) { pfEditVerdict = (uint)tagVSQueryEditResult.QER_EditNotOK; prgfMoreInfo = (uint)(tagVSQueryEditResultFlags.QER_InMemoryEditNotAllowed | tagVSQueryEditResultFlags.QER_ReadOnlyNotUnderScc // TODO: Specialize to SCC? ); } } } catch (Exception ex) { IAnkhErrorHandler eh = GetService<IAnkhErrorHandler>(); if (eh != null && eh.IsEnabled(ex)) eh.OnError(ex); else throw; } return VSConstants.S_OK; }
public override void OnExecute(CommandEventArgs e) { HybridCollection <string> dirs = new HybridCollection <string>(StringComparer.OrdinalIgnoreCase); foreach (SvnItem i in e.Selection.GetSelectedSvnItems(true)) { SvnDirectory dir = i.ParentDirectory; if (dir != null && dir.NeedsWorkingCopyUpgrade && !dirs.Contains(dir.FullPath)) { dirs.Add(dir.FullPath); } else if (i.IsDirectory && i.AsDirectory().NeedsWorkingCopyUpgrade&& !dirs.Contains(i.FullPath)) { dirs.Add(i.FullPath); } } e.GetService <IProgressRunner>().RunModal(CommandStrings.UpgradingWorkingCopy, delegate(object sender, ProgressWorkerArgs a) { HybridCollection <string> done = new HybridCollection <string>(StringComparer.OrdinalIgnoreCase); foreach (string dir in dirs) { SvnInfoArgs ia = new SvnInfoArgs(); ia.ThrowOnError = false; if (done.Contains(dir)) { continue; } if (a.Client.Info(dir, ia, null) || ia.LastException.SvnErrorCode != SvnErrorCode.SVN_ERR_WC_UPGRADE_REQUIRED) { continue; } SvnUpgradeArgs ua = new SvnUpgradeArgs(); ua.ThrowOnError = false; /* Capture the already upgraded directories to avoid a lot of work */ ua.Notify += delegate(object sender2, SvnNotifyEventArgs n) { if (n.Action == SvnNotifyAction.UpgradedDirectory) { if (!done.Contains(n.FullPath)) { done.Add(n.FullPath); } } }; string tryDir = dir; while (true) { if (a.Client.Upgrade(tryDir, ua) || ua.LastException.SvnErrorCode != SvnErrorCode.SVN_ERR_WC_INVALID_OP_ON_CWD) { break; } string pd = SvnTools.GetNormalizedDirectoryName(tryDir); if (pd == tryDir || string.IsNullOrEmpty(pd)) { break; } tryDir = pd; } } }); if (dirs.Count > 0) { StatusCache.ResetUpgradeWarning(); } }
private static void CheckOutAndOpenProject(CommandEventArgs e, SvnUriTarget checkoutLocation, SvnRevision revision, Uri projectTop, string localDir, Uri projectUri) { IProgressRunner runner = e.GetService <IProgressRunner>(); runner.RunModal(CommandStrings.CheckingOutSolution, delegate(object sender, ProgressWorkerArgs ee) { PerformCheckout(ee, checkoutLocation, revision, localDir); }); Uri file = projectTop.MakeRelativeUri(projectUri); string projectFile = SvnTools.GetNormalizedFullPath(Path.Combine(localDir, SvnTools.UriPartToPath(file.ToString()))); AddProject(e, projectFile); using (ProjectAddInfoDialog pai = new ProjectAddInfoDialog()) { IAnkhSolutionSettings ss = e.GetService <IAnkhSolutionSettings>(); ISvnStatusCache cache = e.GetService <ISvnStatusCache>(); SvnItem rootItem; pai.EnableSlnConnection = false; if (ss == null || cache == null || string.IsNullOrEmpty(ss.ProjectRoot) || !SvnItem.IsBelowRoot(localDir, ss.ProjectRoot) || null == (rootItem = cache[localDir])) { pai.EnableExternal = false; pai.EnableCopy = false; } else { SvnItem dir = rootItem.Parent; if (ss.ProjectRootSvnItem != null && ss.ProjectRootSvnItem.IsVersioned) { HybridCollection <string> dirs = new HybridCollection <string>(); SvnItem exDir = dir; while (exDir != null && exDir.IsBelowPath(ss.ProjectRoot)) { if (exDir.IsVersioned && exDir.WorkingCopy == ss.ProjectRootSvnItem.WorkingCopy) { dirs.Add(exDir.FullPath); } exDir = exDir.Parent; } pai.SetExternalDirs(dirs); pai.EnableExternal = true; } else { pai.EnableExternal = false; } if (rootItem.WorkingCopy != null && dir.WorkingCopy != null) { pai.EnableCopy = (rootItem.WorkingCopy.RepositoryRoot == dir.WorkingCopy.RepositoryRoot) && (rootItem.WorkingCopy.RepositoryId == dir.WorkingCopy.RepositoryId); } else { pai.EnableCopy = false; } } if (pai.ShowDialog(e.Context) == DialogResult.OK) { switch (pai.SelectedMode) { case ProjectAddMode.External: if (pai.ExternalLocation != null) { using (SvnClient cl = e.GetService <ISvnClientPool>().GetNoUIClient()) { string externals; if (!cl.TryGetProperty(pai.ExternalLocation, SvnPropertyNames.SvnExternals, out externals)) { externals = ""; } SvnExternalItem sei; if (pai.ExternalLocked) { sei = new SvnExternalItem(SvnItem.SubPath(localDir, pai.ExternalLocation), checkoutLocation.Uri, revision, revision); } else { sei = new SvnExternalItem(SvnItem.SubPath(localDir, pai.ExternalLocation), checkoutLocation.Uri); } externals = sei.ToString(true) + Environment.NewLine + externals; cl.SetProperty(pai.ExternalLocation, SvnPropertyNames.SvnExternals, externals); } } break; case ProjectAddMode.Copy: using (SvnClient cl = e.GetService <ISvnClientPool>().GetClient()) { string tmpDir = localDir + "-Src-copyTmp"; Directory.CreateDirectory(tmpDir); Directory.Move(Path.Combine(localDir, SvnClient.AdministrativeDirectoryName), Path.Combine(tmpDir, SvnClient.AdministrativeDirectoryName)); SvnCopyArgs ma = new SvnCopyArgs(); ma.MetaDataOnly = true; cl.Copy(tmpDir, localDir, ma); SvnItem.DeleteDirectory(tmpDir, true); cache.MarkDirtyRecursive(localDir); } break; case ProjectAddMode.Unversioned: cache.MarkDirtyRecursive(localDir); SvnItem.DeleteDirectory(Path.Combine(localDir, SvnClient.AdministrativeDirectoryName), true); e.GetService <IFileStatusMonitor>().ScheduleGlyphUpdate(projectFile); // And everything else in the project break; } } } }
public override void OnExecute(CommandEventArgs e) { List <SvnItem> toRevert = new List <SvnItem>(); HybridCollection <string> contained = new HybridCollection <string>(StringComparer.OrdinalIgnoreCase); HybridCollection <string> checkedItems = null; foreach (SvnItem i in e.Selection.GetSelectedSvnItems(false)) { if (contained.Contains(i.FullPath)) { continue; } contained.Add(i.FullPath); if (i.IsModified || (i.IsVersioned && i.IsDocumentDirty) || i.IsConflicted) { toRevert.Add(i); } } Predicate <SvnItem> initialCheckedFilter = null; if (toRevert.Count > 0) { checkedItems = new HybridCollection <string>(contained, StringComparer.OrdinalIgnoreCase); initialCheckedFilter = delegate(SvnItem item) { return(checkedItems.Contains(item.FullPath)); }; } foreach (SvnItem i in e.Selection.GetSelectedSvnItems(true)) { if (contained.Contains(i.FullPath)) { continue; } contained.Add(i.FullPath); if (i.IsModified || (i.IsVersioned && i.IsDocumentDirty)) { toRevert.Add(i); } } if (e.PromptUser || (!e.DontPrompt && !Shift)) { using (PendingChangeSelector pcs = new PendingChangeSelector()) { pcs.Text = CommandStrings.RevertDialogTitle; pcs.PreserveWindowPlacement = true; pcs.LoadItems(toRevert, null, initialCheckedFilter); if (pcs.ShowDialog(e.Context) != DialogResult.OK) { return; } toRevert.Clear(); toRevert.AddRange(pcs.GetSelectedItems()); } } IAnkhOpenDocumentTracker documentTracker = e.GetService <IAnkhOpenDocumentTracker>(); ICollection <string> revertPaths = SvnItem.GetPaths(toRevert); documentTracker.SaveDocuments(revertPaths); // Revert items backwards to make sure we revert children before their ancestors toRevert.Sort(delegate(SvnItem i1, SvnItem i2) { bool add1 = i1.IsAdded || i1.IsReplaced; bool add2 = i2.IsAdded || i2.IsReplaced; if (add1 && !add2) { return(-1); } else if (add2 && !add1) { return(1); } else if (add1 && add2) { return(-StringComparer.OrdinalIgnoreCase.Compare(i1.FullPath, i2.FullPath)); } return(StringComparer.OrdinalIgnoreCase.Compare(i1.FullPath, i2.FullPath)); }); // perform the actual revert using (DocumentLock dl = documentTracker.LockDocuments(revertPaths, DocumentLockType.NoReload)) using (dl.MonitorChangesForReload()) { e.GetService <IProgressRunner>().RunModal(CommandStrings.Reverting, delegate(object sender, ProgressWorkerArgs a) { SvnRevertArgs ra = new SvnRevertArgs(); ra.AddExpectedError(SvnErrorCode.SVN_ERR_WC_NOT_DIRECTORY, SvnErrorCode.SVN_ERR_WC_INVALID_OPERATION_DEPTH); // Parent revert invalidated this change ra.Depth = SvnDepth.Empty; List <SvnItem> toRevertWithInfinity = new List <SvnItem>(); foreach (SvnItem item in toRevert) { if (!a.Client.Revert(item.FullPath, ra)) { switch (ra.LastException.SvnErrorCode) { case SvnErrorCode.SVN_ERR_WC_INVALID_OPERATION_DEPTH: toRevertWithInfinity.Add(item); break; } } } ra = new SvnRevertArgs(); ra.AddExpectedError(SvnErrorCode.SVN_ERR_WC_NOT_DIRECTORY); ra.Depth = SvnDepth.Infinity; foreach (SvnItem item in toRevertWithInfinity) { SvnStatusArgs sa = new SvnStatusArgs(); sa.RetrieveIgnoredEntries = false; sa.IgnoreExternals = true; sa.ThrowOnError = false; bool modifications = false; using (new SharpSvn.Implementation.SvnFsOperationRetryOverride(0)) { if (!a.Client.Status(item.FullPath, sa, delegate(object ss, SvnStatusEventArgs ee) { if (ee.FullPath == item.FullPath) { return; } if (ee.Conflicted || (ee.LocalPropertyStatus != SvnStatus.Normal && ee.LocalPropertyStatus != SvnStatus.None)) { ee.Cancel = modifications = true; } else { switch (ee.LocalNodeStatus) { case SvnStatus.None: case SvnStatus.Normal: case SvnStatus.Ignored: case SvnStatus.External: case SvnStatus.NotVersioned: break; default: ee.Cancel = modifications = true; break; } } })) { modifications = true; } } if (!modifications) { a.Client.Revert(item.FullPath, ra); } } }); } }
private void AddActivitySubscription(ActivityStateQuery query) { HybridCollection<ActivityStateQuery> hybrids; this.trackingRecordPreFilter.TrackActivityStateRecords = true; foreach (string str in query.States) { if (string.CompareOrdinal(str, "*") == 0) { this.trackingRecordPreFilter.TrackActivityStateRecordsClosedState = true; this.trackingRecordPreFilter.TrackActivityStateRecordsExecutingState = true; break; } if (string.CompareOrdinal(str, "Closed") == 0) { this.trackingRecordPreFilter.TrackActivityStateRecordsClosedState = true; } else if (string.CompareOrdinal(str, "Executing") == 0) { this.trackingRecordPreFilter.TrackActivityStateRecordsExecutingState = true; } } if (this.activitySubscriptions == null) { this.activitySubscriptions = new Dictionary<string, HybridCollection<ActivityStateQuery>>(); } if (!this.activitySubscriptions.TryGetValue(query.ActivityName, out hybrids)) { hybrids = new HybridCollection<ActivityStateQuery>(); this.activitySubscriptions[query.ActivityName] = hybrids; } hybrids.Add(query); this.AddActivityName(query.ActivityName); }
/// <summary> /// Provides ToolTip text based on the source control data for a specific node in the project's hierarchy Solution Explorer. /// </summary> /// <param name="hierarchy">[in] Owner hierarchy of node (null if it is a solution).</param> /// <param name="itemidNode">[in] The ID of the node for which the ToolTip is requested.</param> /// <param name="pbstrTooltipText">[out] ToolTip text.</param> /// <returns> /// If the method succeeds, it returns <see cref="F:Microsoft.VisualStudio.VSErr.S_OK"></see>. If it fails, it returns an error code. /// </returns> protected override string GetGlyphTipText(SccHierarchy hierarchy, uint itemidNode) { if (Walker == null || StatusCache == null) { return(null); } HybridCollection <string> files = new HybridCollection <string>(StringComparer.OrdinalIgnoreCase); int n = 0; foreach (string file in Walker.GetSccFiles(hierarchy.Hierarchy, itemidNode, ProjectWalkDepth.Empty, null)) { if (files.Contains(file) || !SvnItem.IsValidPath(file)) { continue; } files.Add(file); SccProjectFile spf; if (ProjectMap.TryGetFile(file, out spf)) { foreach (string subfile in spf.FirstReference.GetSubFiles()) { if (!files.Contains(subfile)) { files.Add(subfile); } } } } StringBuilder sb = new StringBuilder(); string format = (files.Count > 0) ? "{0}: {1}" : "{1}"; int i = 0; foreach (string file in files) { SvnItem item = StatusCache[file]; if (i >= n) // This is a subitem! { if (item.IsModified) { sb.AppendFormat(format, item.Name, Resources.ToolTipModified).AppendLine(); } } if (item.IsConflicted) { sb.AppendFormat(format, item.Name, Resources.ToolTipConflict).AppendLine(); } if (item.IsObstructed) { sb.AppendFormat(format, item.Name, item.IsFile ? Resources.ToolTipFileObstructed : Resources.ToolTipDirObstructed).AppendLine(); } if (!item.Exists && item.IsVersioned && !item.IsDeleteScheduled) { sb.AppendFormat(format, item.Name, Resources.ToolTipDoesNotExist).AppendLine(); } if (item.IsLocked) { sb.AppendFormat(format, item.Name, Resources.ToolTipLocked).AppendLine(); } i++; if (sb.Length > 2048) { break; } } if (sb.Length > 0) { return(sb.ToString().Trim()); // We added newlines } return(null); }
IDictionary<string, int> GetNumberValues(string regKey, string subKey) { if (string.IsNullOrEmpty(regKey)) throw new ArgumentNullException("regKey"); if (string.IsNullOrEmpty(subKey)) throw new ArgumentNullException("subKey"); IDictionary<string, int> values; lock (_lock) { subKey = regKey + "\\" + subKey; using (RegistryKey reg = OpenHKCUKey(subKey)) { if (reg == null) return null; HybridCollection<string> hs = new HybridCollection<string>(); hs.AddRange(reg.GetValueNames()); values = new Dictionary<string, int>(hs.Count); foreach (string item in hs) { int width; if (RegistryUtils.TryGetIntValue(reg, item, out width) && width > 0) values.Add(item, width); } } } return values; }
public IEnumerable <Uri> GetRepositoryUris(bool forBrowse) { HybridCollection <Uri> uris = new HybridCollection <Uri>(); if (ProjectRootUri != null) { uris.Add(ProjectRootUri); } // Global keys (over all versions) using (RegistryKey rk = Config.OpenGlobalKey("Repositories")) { if (rk != null) { LoadUris(uris, rk); } } // Per hive using (RegistryKey rk = Config.OpenInstanceKey("Repositories")) { if (rk != null) { LoadUris(uris, rk); } } // Per user + Per hive using (RegistryKey rk = Config.OpenUserInstanceKey("Repositories")) { if (rk != null) { LoadUris(uris, rk); } } // Finally add the last used list from TortoiseSVN try { using (RegistryKey rk = Registry.CurrentUser.OpenSubKey( "SOFTWARE\\TortoiseSVN\\History\\repoURLS", RegistryKeyPermissionCheck.ReadSubTree)) { if (rk != null) { LoadUris(uris, rk); } } } catch (SecurityException) { /* Ignore no read only access; stupid sysadmins */ } IAnkhConfigurationService configSvc = GetService <IAnkhConfigurationService>(); if (configSvc != null) { foreach (string u in configSvc.GetRecentReposUrls()) { Uri uri; if (u != null && Uri.TryCreate(u, UriKind.Absolute, out uri)) { if (!uris.Contains(uri)) { uris.Add(uri); } } } } return(uris); }
public bool SaveAllDocumentsExcept(IEnumerable<string> paths) { if (paths == null) throw new ArgumentNullException("paths"); HybridCollection<string> pathsCol = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); pathsCol.UniqueAddRange(paths); bool ok = true; foreach (SccDocumentData data in _docMap.Values) { if (!pathsCol.Contains(data.Name)) { if (!data.SaveDocument(RunningDocumentTable)) ok = false; } } return ok; }
public override void OnExecute(CommandEventArgs e) { ILastChangeInfo ci = e.GetService<ILastChangeInfo>(); if (ci != null) ci.SetLastChange(null, null); SvnRevision rev; bool allowUnversionedObstructions = false; bool updateExternals = true; bool setDepthInfinity = true; IAnkhSolutionSettings settings = e.GetService<IAnkhSolutionSettings>(); IFileStatusCache cache = e.GetService<IFileStatusCache>(); IProjectFileMapper mapper = e.GetService<IProjectFileMapper>(); Uri reposRoot = null; if (IsHeadCommand(e.Command) || e.DontPrompt) rev = SvnRevision.Head; else if (IsSolutionCommand(e.Command)) { SvnItem projectItem = settings.ProjectRootSvnItem; Debug.Assert(projectItem != null, "Has item"); using (UpdateDialog ud = new UpdateDialog()) { ud.ItemToUpdate = projectItem; ud.Revision = SvnRevision.Head; if (ud.ShowDialog(e.Context) != DialogResult.OK) return; rev = ud.Revision; allowUnversionedObstructions = ud.AllowUnversionedObstructions; updateExternals = ud.UpdateExternals; setDepthInfinity = ud.SetDepthInfinty; } } else if (IsFolderCommand(e.Command)) { SvnItem dirItem = EnumTools.GetFirst(e.Selection.GetSelectedSvnItems(false)); Debug.Assert(dirItem != null && dirItem.IsDirectory && dirItem.IsVersioned); using (UpdateDialog ud = new UpdateDialog()) { ud.Text = CommandStrings.UpdateFolder; ud.FolderLabelText = CommandStrings.UpdateFolderLabel; ud.ItemToUpdate = dirItem; ud.Revision = SvnRevision.Head; if (ud.ShowDialog(e.Context) != DialogResult.OK) return; rev = ud.Revision; allowUnversionedObstructions = ud.AllowUnversionedObstructions; updateExternals = ud.UpdateExternals; setDepthInfinity = ud.SetDepthInfinty; } } else { // We checked there was only a single repository to select a revision // from in OnUpdate, so we can suffice with only calculate the path SvnItem si = null; SvnOrigin origin = null; foreach (SvnProject p in GetSelectedProjects(e)) { ISvnProjectInfo pi = mapper.GetProjectInfo(p); if (pi == null || pi.ProjectDirectory == null) continue; SvnItem item = cache[pi.ProjectDirectory]; if (!item.IsVersioned) continue; if (si == null && origin == null) { si = item; origin = new SvnOrigin(item); reposRoot = item.WorkingCopy.RepositoryRoot; } else { si = null; string urlPath1 = origin.Uri.AbsolutePath; string urlPath2 = item.Uri.AbsolutePath; int i = 0; while (i < urlPath1.Length && i < urlPath2.Length && urlPath1[i] == urlPath2[i]) { i++; } while (i > 0 && urlPath1[i - 1] != '/') i--; origin = new SvnOrigin(new Uri(origin.Uri, urlPath1.Substring(0, i)), origin.RepositoryRoot); } } Debug.Assert(origin != null); using (UpdateDialog ud = new UpdateDialog()) { ud.Text = CommandStrings.UpdateProject; if (si != null) ud.ItemToUpdate = si; else { ud.SvnOrigin = origin; ud.SetMultiple(true); } ud.Revision = SvnRevision.Head; if (ud.ShowDialog(e.Context) != DialogResult.OK) return; rev = ud.Revision; allowUnversionedObstructions = ud.AllowUnversionedObstructions; updateExternals = ud.UpdateExternals; setDepthInfinity = ud.SetDepthInfinty; } } Dictionary<string, SvnItem> itemsToUpdate = new Dictionary<string, SvnItem>(StringComparer.OrdinalIgnoreCase); Dictionary<string, List<string>> groups = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase); // Get a list of all documents below the specified paths that are open in editors inside VS HybridCollection<string> lockPaths = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); IAnkhOpenDocumentTracker documentTracker = e.GetService<IAnkhOpenDocumentTracker>(); foreach (SvnItem item in GetAllUpdateRoots(e)) { // GetAllUpdateRoots can (and probably will) return duplicates! if (itemsToUpdate.ContainsKey(item.FullPath) || !item.IsVersioned) continue; SvnWorkingCopy wc = item.WorkingCopy; if (!IsHeadCommand(e.Command) && reposRoot != null) { // Specific revisions are only valid on a single repository! if (wc != null && wc.RepositoryRoot != reposRoot) continue; } List<string> inWc; if (!groups.TryGetValue(wc.FullPath, out inWc)) { inWc = new List<string>(); groups.Add(wc.FullPath, inWc); } inWc.Add(item.FullPath); itemsToUpdate.Add(item.FullPath, item); foreach (string file in documentTracker.GetDocumentsBelow(item.FullPath)) { if (!lockPaths.Contains(file)) lockPaths.Add(file); } } documentTracker.SaveDocuments(lockPaths); // Make sure all files are saved before updating/merging! using (DocumentLock lck = documentTracker.LockDocuments(lockPaths, DocumentLockType.NoReload)) using (lck.MonitorChangesForReload()) { SvnUpdateResult updateResult = null; ProgressRunnerArgs pa = new ProgressRunnerArgs(); pa.CreateLog = true; string title; if (IsSolutionCommand(e.Command)) title = CommandStrings.UpdatingSolution; else if (IsFolderCommand(e.Command)) title = CommandStrings.UpdatingFolder; else title = CommandStrings.UpdatingProject; e.GetService<IProgressRunner>().RunModal(title, pa, delegate(object sender, ProgressWorkerArgs a) { PerformUpdate(e, a, rev, allowUnversionedObstructions, updateExternals, setDepthInfinity, groups.Values, out updateResult); }); if (ci != null && updateResult != null && IsSolutionCommand(e.Command)) { ci.SetLastChange("Updated to:", updateResult.Revision.ToString()); } } }
public override void Reload(IEnumerable<string> paths) { if (paths == null) throw new ArgumentNullException("paths"); StopMonitor(); // Make sure we have no further locks while reloading! HybridCollection<string> changed = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); changed.AddRange(paths); IProjectFileMapper mapper = _tracker.GetService<IProjectFileMapper>(); if (!string.IsNullOrEmpty(mapper.SolutionFilename) && changed.Contains(mapper.SolutionFilename)) { // Ok; we are going to reload the solution itself _tracker.SaveAllDocumentsExcept(changed); // Make sure everything that is dirty is saved // let's remove all documents that are in the solution from the changed list foreach (string file in mapper.GetAllFilesOfAllProjects()) { changed.Remove(file); } // The solution was just removed; add it back changed.Add(mapper.SolutionFilename); } for (int i = 0; i < changed.Count; i++) { string ch = changed[i]; SccDocumentData dd; if (_tracker._docMap.TryGetValue(ch, out dd)) { if (!dd.Reload(true, false)) { string parentDocument = _tracker.GetParentDocument(dd); if (string.IsNullOrEmpty(parentDocument)) parentDocument = mapper.SolutionFilename; if (!string.IsNullOrEmpty(parentDocument) && !changed.Contains(parentDocument)) { if (!_locked.Contains(parentDocument)) { // The parent is not on our changed or locked list.. so make sure it is saved _tracker.SaveDocument(parentDocument); } changed.Add(parentDocument); } } } } }
/// <summary> /// Schedules a dirty check for the specified document /// </summary> /// <param name="path">The path.</param> public void ScheduleDirtyCheck(string path) { if (path == null) throw new ArgumentNullException("path"); SvnItem item = Cache[path]; if (!item.IsVersioned || item.IsModified) return; // Not needed lock (_lock) { if (_dirtyCheck == null) _dirtyCheck = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); if (!_dirtyCheck.Contains(path)) _dirtyCheck.Add(path); PostIdle(); } }
public override void OnExecute(CommandEventArgs e) { SvnItem theItem = null; string path; bool allowObstructions = false; string projectRoot = e.GetService <IAnkhSolutionSettings>().ProjectRoot; if (e.Command == AnkhCommand.SolutionSwitchDialog) { path = projectRoot; } else if (e.Command == AnkhCommand.SwitchProject) { IProjectFileMapper mapper = e.GetService <IProjectFileMapper>(); path = null; foreach (SccProject item in e.Selection.GetSelectedProjects(true)) { ISccProjectInfo pi = mapper.GetProjectInfo(item); if (pi == null) { continue; } path = pi.ProjectDirectory; break; } if (string.IsNullOrEmpty(path)) { return; } } else { foreach (SvnItem item in e.Selection.GetSelectedSvnItems(false)) { if (item.IsVersioned) { theItem = item; break; } return; } path = theItem.FullPath; } ISvnStatusCache statusCache = e.GetService <ISvnStatusCache>(); SvnItem pathItem = statusCache[path]; Uri uri = pathItem.Uri; if (uri == null) { return; // Should never happen on a real workingcopy } SvnUriTarget target; SvnRevision revision = SvnRevision.None; if (e.Argument is string) { target = SvnUriTarget.FromString((string)e.Argument, true); revision = (target.Revision != SvnRevision.None) ? target.Revision : SvnRevision.Head; } else if (e.Argument is Uri) { target = (Uri)e.Argument; } else { using (SwitchDialog dlg = new SwitchDialog()) { dlg.Context = e.Context; dlg.LocalPath = path; dlg.RepositoryRoot = e.GetService <ISvnStatusCache>()[path].WorkingCopy.RepositoryRoot; dlg.SwitchToUri = uri; dlg.Revision = SvnRevision.Head; if (dlg.ShowDialog(e.Context) != DialogResult.OK) { return; } target = dlg.SwitchToUri; revision = dlg.Revision; allowObstructions = dlg.AllowUnversionedObstructions; } } // Get a list of all documents below the specified paths that are open in editors inside VS HybridCollection <string> lockPaths = new HybridCollection <string>(StringComparer.OrdinalIgnoreCase); IAnkhOpenDocumentTracker documentTracker = e.GetService <IAnkhOpenDocumentTracker>(); foreach (string file in documentTracker.GetDocumentsBelow(path)) { if (!lockPaths.Contains(file)) { lockPaths.Add(file); } } documentTracker.SaveDocuments(lockPaths); // Make sure all files are saved before merging! using (DocumentLock lck = documentTracker.LockDocuments(lockPaths, DocumentLockType.NoReload)) using (lck.MonitorChangesForReload()) { Uri newRepositoryRoot = null; e.GetService <IProgressRunner>().RunModal(CommandStrings.SwitchingTitle, delegate(object sender, ProgressWorkerArgs a) { SvnSwitchArgs args = new SvnSwitchArgs(); args.AllowObstructions = allowObstructions; args.AddExpectedError(SvnErrorCode.SVN_ERR_WC_INVALID_SWITCH); if (revision != SvnRevision.None) { args.Revision = revision; } e.GetService <IConflictHandler>().RegisterConflictHandler(args, a.Synchronizer); if (!a.Client.Switch(path, target, args)) { if (args.LastException.SvnErrorCode != SvnErrorCode.SVN_ERR_WC_INVALID_SWITCH) { return; } // source/target repository is different, check if we can fix this by relocating SvnInfoEventArgs iea; if (a.Client.GetInfo(target, out iea)) { if (pathItem.WorkingCopy.RepositoryId != iea.RepositoryId) { e.Context.GetService <IAnkhDialogOwner>() .MessageBox.Show("Cannot switch to different repository because the repository UUIDs are different", "Cannot switch", MessageBoxButtons.OK, MessageBoxIcon.Error); } else if (pathItem.WorkingCopy.RepositoryRoot != iea.RepositoryRoot) { newRepositoryRoot = iea.RepositoryRoot; } else if (pathItem.WorkingCopy.RepositoryId == Guid.Empty) { // No UUIDs and RepositoryRoot equal. Throw/show error? throw args.LastException; } } } }); if (newRepositoryRoot != null && DialogResult.Yes == e.Context.GetService <IAnkhDialogOwner>() .MessageBox.Show(string.Format("The repository root specified is different from the one in your " + "working copy. Would you like to relocate '{0}' from '{1}' to '{2}'?", pathItem.WorkingCopy.FullPath, pathItem.WorkingCopy.RepositoryRoot, newRepositoryRoot), "Relocate", MessageBoxButtons.YesNo, MessageBoxIcon.Question)) { // We can fix this by relocating string wcRoot = pathItem.WorkingCopy.FullPath; try { e.GetService <IProgressRunner>().RunModal( CommandStrings.RelocatingTitle, delegate(object sender, ProgressWorkerArgs a) { a.Client.Relocate(wcRoot, pathItem.WorkingCopy.RepositoryRoot, newRepositoryRoot); }); } finally { statusCache.MarkDirtyRecursive(wcRoot); e.GetService <IFileStatusMonitor>().ScheduleGlyphUpdate(statusCache.GetCachedBelow(wcRoot)); } if (DialogResult.Yes == e.Context.GetService <IAnkhDialogOwner>() .MessageBox.Show(string.Format("Would you like to try to switch '{0}' to '{1}' again?", path, target), "Switch", MessageBoxButtons.YesNo, MessageBoxIcon.Question)) { // Try to switch again e.GetService <IProgressRunner>().RunModal( CommandStrings.SwitchingTitle, delegate(object sender, ProgressWorkerArgs a) { SvnSwitchArgs args = new SvnSwitchArgs(); if (revision != SvnRevision.None) { args.Revision = revision; } args.AllowObstructions = allowObstructions; e.GetService <IConflictHandler>().RegisterConflictHandler(args, a.Synchronizer); a.Client.Switch(path, target, args); }); } } } }
internal void HandleEvent(AnkhCommand command) { List<SvnProject> dirtyProjects; HybridCollection<string> dirtyCheck; HybridCollection<string> maybeAdd; AnkhSccProvider provider = Context.GetService<AnkhSccProvider>(); lock (_lock) { _posted = false; _onIdle = false; if (provider == null) return; dirtyProjects = _dirtyProjects; dirtyCheck = _dirtyCheck; maybeAdd = _maybeAdd; _dirtyProjects = null; _dirtyCheck = null; _maybeAdd = null; } if (dirtyCheck != null) foreach (string file in dirtyCheck) { DocumentTracker.CheckDirty(file); } if (dirtyProjects != null) { foreach (SvnProject project in dirtyProjects) { if (project.RawHandle == null) { if (project.IsSolution) provider.UpdateSolutionGlyph(); continue; // All IVsSccProjects have a RawHandle } try { project.RawHandle.SccGlyphChanged(0, null, null, null); } catch { } } } if (maybeAdd != null) using (SvnClient cl = GetService<ISvnClientPool>().GetNoUIClient()) { foreach (string file in maybeAdd) { SvnItem item = Cache[file]; // Only add // * files // * that are unversioned // * that are addable // * that are not ignored // * and just to be sure: that are still part of the solution if (item.IsFile && !item.IsVersioned && item.IsVersionable && !item.IsIgnored && item.InSolution) { SvnAddArgs aa = new SvnAddArgs(); aa.ThrowOnError = false; // Just ignore errors here; make the user add them themselves aa.AddParents = true; cl.Add(item.FullPath, aa); } } } }
/// <summary> /// Returns false if the AddToSubversionDialog has been cancelled, true otherwise /// </summary> /// <param name="e"></param> /// <param name="projectInfo"></param> /// <param name="solutionReposRoot"></param> /// <param name="shouldMarkAsManaged"></param> /// <param name="storeReference"></param> /// <returns></returns> static bool CheckoutWorkingCopyForProject(CommandEventArgs e, SccProject project, ISccProjectInfo projectInfo, Uri solutionReposRoot, out bool shouldMarkAsManaged, out bool storeReference) { shouldMarkAsManaged = false; storeReference = false; using (SvnClient cl = e.GetService <ISvnClientPool>().GetClient()) using (AddProjectToSubversion dialog = new AddProjectToSubversion()) { dialog.Context = e.Context; dialog.PathToAdd = projectInfo.ProjectDirectory; dialog.RepositoryAddUrl = solutionReposRoot; if (e.Argument is IAnkhSccService) { dialog.CommitAllVisible = false; dialog.CommitAllFiles = false; } else { dialog.CommitAllFiles = true; } if (dialog.ShowDialog(e.Context) != DialogResult.OK) { return(false); // User cancelled the "Add to subversion" dialog, don't set as managed by Ankh } if (!dialog.CommitAllFiles) { Collection <SvnInfoEventArgs> info; SvnInfoArgs ia = new SvnInfoArgs(); ia.ThrowOnError = false; if (!cl.GetInfo(dialog.RepositoryAddUrl, ia, out info)) { // Target uri doesn't exist in the repository, let's create if (!RemoteCreateDirectory(e, dialog.Text, dialog.RepositoryAddUrl, cl)) { return(false); // Create failed; bail out } } // Create working copy SvnCheckOutArgs coArg = new SvnCheckOutArgs(); coArg.AllowObstructions = true; cl.CheckOut(dialog.RepositoryAddUrl, dialog.WorkingCopyDir, coArg); } else { // Cache some values before thread marshalling HybridCollection <string> projectFiles = new HybridCollection <string>(StringComparer.OrdinalIgnoreCase); string wcDir = dialog.WorkingCopyDir; Uri reposUrl = dialog.RepositoryAddUrl; string logMessage; projectFiles.UniqueAddRange(e.GetService <IProjectFileMapper>().GetAllFilesOf(project)); using (CreateDirectoryDialog dlg = new CreateDirectoryDialog()) { dlg.Text = CommandStrings.ImportingTitle; dlg.NewDirectoryName = reposUrl.ToString(); dlg.NewDirectoryReadonly = true; if (dlg.ShowDialog(e.Context) != DialogResult.OK) { return(false); } logMessage = dlg.LogMessage; } IAnkhOpenDocumentTracker documentTracker = e.GetService <IAnkhOpenDocumentTracker>(); documentTracker.SaveDocuments(projectFiles); // Make sure all files are saved before updating/merging! using (DocumentLock lck = documentTracker.LockDocuments(projectFiles, DocumentLockType.NoReload)) using (lck.MonitorChangesForReload()) { e.GetService <IProgressRunner>().RunModal(CommandStrings.ImportingTitle, delegate(object sender, ProgressWorkerArgs a) { SvnImportArgs importArgs = new SvnImportArgs(); importArgs.LogMessage = logMessage; importArgs.Filter += delegate(object ieSender, SvnImportFilterEventArgs ie) { if (ie.NodeKind != SvnNodeKind.Directory) { ie.Filter = !projectFiles.Contains(ie.FullPath); } else { bool filter = true; foreach (string p in projectFiles) { if (SvnItem.IsBelowRoot(p, ie.FullPath)) { filter = false; break; } } if (filter) { ie.Filter = true; } } }; a.Client.Import(wcDir, reposUrl, importArgs); }); } } shouldMarkAsManaged = dialog.MarkAsManaged; storeReference = dialog.WriteCheckOutInformation; } return(true); }
public override void OnExecute(CommandEventArgs e) { if (e.Argument != null) { ShowUpdate(e); return; } int interval = 24 * 6; // 6 days IAnkhConfigurationService config = e.GetService <IAnkhConfigurationService>(); if (config.Instance.DisableUpdateCheck) { return; } using (RegistryKey rk = config.OpenUserInstanceKey("UpdateCheck")) { object value = rk.GetValue("Interval"); if (value is int) { interval = (int)value; if (interval <= 0) { return; } } } Version version = GetCurrentVersion(e.Context); Version osVersion = Environment.OSVersion.Version; StringBuilder sb = new StringBuilder(); sb.Append("http://svc.ankhsvn.net/svc/"); if (IsDevVersion()) { sb.Append("dev/"); } sb.Append("update-info/"); sb.Append(version.ToString(2)); sb.Append(".xml"); sb.Append("?av="); sb.Append(version); sb.Append("&vs="); sb.Append(VSVersion.FullVersion); sb.Append("&os="); sb.Append(osVersion); if (IsDevVersion()) { sb.Append("&dev=1"); } sb.AppendFormat(CultureInfo.InvariantCulture, "&iv={0}", interval); int x = 0; // Create some hashcode that is probably constant and unique for all users // using the same IP address, but not translatable to a single user try { foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces()) { string type = ni.NetworkInterfaceType.ToString(); if (type.Contains("Ethernet") || type.Contains("Wireless")) { x ^= ni.GetPhysicalAddress().GetHashCode(); } } } catch { } sb.AppendFormat(CultureInfo.InvariantCulture, "&xx={0}&pc={1}", x, Environment.ProcessorCount); try { using (RegistryKey rk = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP")) { if (rk != null) { sb.Append("&dn="); Regex re = new Regex("^[vV]([0-9]+\\.[0-9]+)(\\.[0-9]+)*", RegexOptions.Singleline); bool first = true; HybridCollection <string> vers = new HybridCollection <string>(); foreach (string s in rk.GetSubKeyNames()) { Match m = re.Match(s); if (m.Success) { string v = m.Groups[1].Value; if (vers.Contains(v)) { continue; } vers.Add(v); if (first) { first = false; } else { sb.Append(','); } sb.Append(v); } } } } } catch { } WebRequest wr; try { wr = WebRequest.Create(new Uri(sb.ToString())); } catch (System.Configuration.ConfigurationException) { // The global .Net or Visual Studio configuration probably contains an invalid (proxy) configuration return; // Not our problem } HttpWebRequest hwr = wr as HttpWebRequest; if (hwr != null) { hwr.AllowAutoRedirect = true; hwr.AllowWriteStreamBuffering = true; hwr.UserAgent = string.Format("AnkhSVN/{0} VisualStudio/{1} Windows/{2}", version, VSVersion.FullVersion, osVersion); } try { wr.BeginGetResponse(OnResponse, wr); } catch (NotSupportedException) { /* Raised when an invalid proxy server setting is set */ } }
public DocumentLock LockDocuments(IEnumerable<string> paths, DocumentLockType lockType) { if (paths == null) throw new ArgumentNullException("paths"); HybridCollection<string> locked = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); HybridCollection<string> ignoring = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); HybridCollection<string> readOnly = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); foreach (string path in paths) { SccDocumentData dd; if (_docMap.TryGetValue(path, out dd)) { if (!locked.Contains(path)) locked.Add(path); if (!ignoring.Contains(path) && dd.IgnoreFileChanges(true)) ignoring.Add(path); if (lockType >= DocumentLockType.ReadOnly && !readOnly.Contains(path) && !dd.IsReadOnly()) { // Don't set read-only twice!!! if (dd.SetReadOnly(true)) readOnly.Add(path); } } } return new SccDocumentLock(this, locked, ignoring, readOnly); }
public override void OnExecute(CommandEventArgs e) { GitPullArgs args = new GitPullArgs(); string repositoryRoot; var repositoryRoots = new HashSet<string>(FileSystemUtil.StringComparer); foreach (var projectRoot in GetAllRoots(e)) { if ( GitTools.TryGetRepositoryRoot(projectRoot.FullPath, out repositoryRoot) && !repositoryRoots.Contains(repositoryRoot) ) repositoryRoots.Add(repositoryRoot); } if (repositoryRoots.Count > 1) { throw new InvalidOperationException("Pulling of multiple repository roots is not supported"); } repositoryRoot = repositoryRoots.Single(); if (e.Command == VisualGitCommand.PendingChangesPullEx) { if (!QueryParameters(e, repositoryRoot, args)) return; } else { args.MergeStrategy = GitMergeStrategy.DefaultForBranch; } GitPullResult result = null; ProgressRunnerArgs pa = new ProgressRunnerArgs(); pa.CreateLog = true; pa.TransportClientArgs = args; // Get a list of all documents below the specified paths that are open in editors inside VS HybridCollection<string> lockPaths = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); IVisualGitOpenDocumentTracker documentTracker = e.GetService<IVisualGitOpenDocumentTracker>(); foreach (string file in documentTracker.GetDocumentsBelow(repositoryRoot)) { if (!lockPaths.Contains(file)) lockPaths.Add(file); } documentTracker.SaveDocuments(lockPaths); // Make sure all files are saved before merging! using (DocumentLock lck = documentTracker.LockDocuments(lockPaths, DocumentLockType.NoReload)) using (lck.MonitorChangesForReload()) { GitException exception = null; e.GetService<IProgressRunner>().RunModal(CommandStrings.PullingSolution, pa, delegate(object sender, ProgressWorkerArgs a) { e.GetService<IConflictHandler>().RegisterConflictHandler(args, a.Synchronizer); try { a.Client.Pull(repositoryRoot, args, out result); } catch (GitException ex) { exception = ex; } }); if (exception != null) { e.GetService<IVisualGitErrorHandler>().OnWarning(exception); } } }
public SccDocumentLock(OpenDocumentTracker tracker, HybridCollection<string> locked, HybridCollection<string> ignoring, HybridCollection<string> readOnly) { if (tracker == null) throw new ArgumentNullException("tracker"); else if (locked == null) throw new ArgumentNullException("locked"); else if (ignoring == null) throw new ArgumentNullException("ignoring"); else if (readOnly == null) throw new ArgumentNullException("readOnly"); _tracker = tracker; _locked = locked; _ignoring = ignoring; _readonly = readOnly; _fsIgnored = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); _changedPaths = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); _monitor = new Dictionary<uint, string>(); _altMonitor = new Dictionary<string, FileInfo>(); _change = tracker.GetService<IVsFileChangeEx>(typeof(SVsFileChangeEx)); foreach (string file in locked) { // This files auto reload could not be suspended by calling Ignore on the document // We must therefore stop posting messages to it by stopping it in the change monitor // But to be able to tell if there are changes.. We keep some stats ourselves if (!ignoring.Contains(file) && ErrorHandler.Succeeded(_change.IgnoreFile(0, file, 1))) { _fsIgnored.Add(file); FileInfo info = new FileInfo(file); info.Refresh(); if (info.Exists) { GC.KeepAlive(info.LastWriteTime); GC.KeepAlive(info.CreationTime); GC.KeepAlive(info.Length); } _altMonitor.Add(file, info); } } }
public SccDocumentLock(OpenDocumentTracker tracker, HybridCollection <string> locked, HybridCollection <string> ignoring, HybridCollection <string> readOnly) { ThreadHelper.ThrowIfNotOnUIThread(); if (tracker == null) { throw new ArgumentNullException("tracker"); } else if (locked == null) { throw new ArgumentNullException("locked"); } else if (ignoring == null) { throw new ArgumentNullException("ignoring"); } else if (readOnly == null) { throw new ArgumentNullException("readOnly"); } _tracker = tracker; _locked = locked; _ignoring = ignoring; _readonly = readOnly; _fsIgnored = new HybridCollection <string>(StringComparer.OrdinalIgnoreCase); _changedPaths = new HybridCollection <string>(StringComparer.OrdinalIgnoreCase); _monitor = new Dictionary <uint, string>(); _altMonitor = new Dictionary <string, FileInfo>(); _change = tracker.GetService <IVsFileChangeEx>(typeof(SVsFileChangeEx)); foreach (string file in locked) { // This files auto reload could not be suspended by calling Ignore on the document // We must therefore stop posting messages to it by stopping it in the change monitor // But to be able to tell if there are changes.. We keep some stats ourselves if (!ignoring.Contains(file) && VSErr.Succeeded(_change.IgnoreFile(0, file, 1))) { _fsIgnored.Add(file); FileInfo info = new FileInfo(file); info.Refresh(); if (info.Exists) { GC.KeepAlive(info.LastWriteTime); GC.KeepAlive(info.CreationTime); GC.KeepAlive(info.Length); } _altMonitor.Add(file, info); } } }
public void ScheduleAddFile(string path) { if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("path"); lock (_lock) { if (_maybeAdd == null) _maybeAdd = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); if (!_maybeAdd.Contains(path)) _maybeAdd.Add(path); PostDirty(true); } }
public override void Reload(IEnumerable <string> paths) { ThreadHelper.ThrowIfNotOnUIThread(); if (paths == null) { throw new ArgumentNullException("paths"); } StopMonitor(); // Make sure we have no further locks while reloading! HybridCollection <string> changed = new HybridCollection <string>(StringComparer.OrdinalIgnoreCase); changed.AddRange(paths); IProjectFileMapper mapper = _tracker.GetService <IProjectFileMapper>(); if (!string.IsNullOrEmpty(mapper.SolutionFilename) && changed.Contains(mapper.SolutionFilename)) { // Ok; we are going to reload the solution itself _tracker.SaveAllDocumentsExcept(changed); // Make sure everything that is dirty is saved // let's remove all documents that are in the solution from the changed list foreach (string file in mapper.GetAllFilesOfAllProjects()) { changed.Remove(file); } // The solution was just removed; add it back changed.Add(mapper.SolutionFilename); } for (int i = 0; i < changed.Count; i++) { string ch = changed[i]; SccDocumentData dd; if (_tracker._docMap.TryGetValue(ch, out dd)) { if (!dd.Reload(true)) { string parentDocument = _tracker.GetParentDocument(dd); if (string.IsNullOrEmpty(parentDocument)) { parentDocument = mapper.SolutionFilename; } if (!string.IsNullOrEmpty(parentDocument) && !changed.Contains(parentDocument)) { if (!_locked.Contains(parentDocument)) { // The parent is not on our changed or locked list.. so make sure it is saved _tracker.SaveDocument(parentDocument); } changed.Add(parentDocument); } } } } }
/// <summary> /// Schedules a dirty check for the specified documents. /// </summary> /// <param name="paths">The paths.</param> public void ScheduleDirtyCheck(IEnumerable<string> paths) { if (paths == null) throw new ArgumentNullException("paths"); lock (_lock) { if (_dirtyCheck == null) _dirtyCheck = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); _dirtyCheck.UniqueAddRange(paths); PostIdle(); } }
public void OnExecute(CommandEventArgs e) { ILogControl logWindow = e.Selection.GetActiveControl <ILogControl>(); IProgressRunner progressRunner = e.GetService <IProgressRunner>(); if (logWindow == null) { return; } List <SvnRevisionRange> revisions = new List <SvnRevisionRange>(); if (e.Command == AnkhCommand.LogRevertTo) { ISvnLogItem item = EnumTools.GetSingle(e.Selection.GetSelection <ISvnLogItem>()); if (item == null) { return; } // Revert to revision, is revert everything after revisions.Add(new SvnRevisionRange(SvnRevision.Working, item.Revision)); } else { foreach (ISvnLogItem item in e.Selection.GetSelection <ISvnLogItem>()) { revisions.Add(new SvnRevisionRange(item.Revision, item.Revision - 1)); } } if (revisions.Count == 0) { return; } IAnkhOpenDocumentTracker tracker = e.GetService <IAnkhOpenDocumentTracker>(); HybridCollection <string> nodes = new HybridCollection <string>(StringComparer.OrdinalIgnoreCase); foreach (SvnOrigin o in logWindow.Origins) { SvnPathTarget pt = o.Target as SvnPathTarget; if (pt == null) { continue; } foreach (string file in tracker.GetDocumentsBelow(pt.FullPath)) { if (!nodes.Contains(file)) { nodes.Add(file); } } } if (nodes.Count > 0) { tracker.SaveDocuments(nodes); // Saves all open documents below all specified origins } using (DocumentLock dl = tracker.LockDocuments(nodes, DocumentLockType.NoReload)) using (dl.MonitorChangesForReload()) { SvnMergeArgs ma = new SvnMergeArgs(); progressRunner.RunModal(LogStrings.Reverting, delegate(object sender, ProgressWorkerArgs ee) { foreach (SvnOrigin item in logWindow.Origins) { SvnPathTarget target = item.Target as SvnPathTarget; if (target == null) { continue; } ee.Client.Merge(target.FullPath, target, revisions, ma); } }); } }
static void Resolve(CommandEventArgs e, GitAccept accept) { HybridCollection<string> paths = new HybridCollection<string>(StringComparer.OrdinalIgnoreCase); foreach (GitItem item in e.Selection.GetSelectedGitItems(true)) { if (!item.IsConflicted) continue; if (!paths.Contains(item.FullPath)) paths.Add(item.FullPath); } IVisualGitOpenDocumentTracker documentTracker = e.GetService<IVisualGitOpenDocumentTracker>(); documentTracker.SaveDocuments(paths); // Make sure all files are saved before updating/merging! using (DocumentLock lck = documentTracker.LockDocuments(paths, DocumentLockType.NoReload)) using (lck.MonitorChangesForReload()) using (GitClient client = e.GetService<IGitClientPool>().GetNoUIClient()) { GitResolveArgs a = new GitResolveArgs(); a.Depth = GitDepth.Empty; foreach (string p in paths) { client.Resolve(p, accept, a); } } }
void InnerRefresh() { using (BatchStartedEventArgs br = BatchRefresh()) { HybridCollection <string> mapped = new HybridCollection <string>(StringComparer.OrdinalIgnoreCase); ISvnStatusCache cache = Cache; foreach (string file in Mapper.GetAllFilesOfAllProjects()) { br.Tick(); _extraFiles.Remove(file); // If we find it here; it is no longer 'extra'! SvnItem item = cache[file]; if (item == null) { continue; } PendingChange pc = UpdatePendingChange(item); if (pc != null) { mapped.Add(pc.FullPath); } } foreach (string file in new List <string>(_extraFiles)) { br.Tick(); SvnItem item = cache[file]; if (item == null) { _extraFiles.Remove(file); continue; } PendingChange pc = UpdatePendingChange(item); if (pc != null) { mapped.Add(pc.FullPath); } else { _extraFiles.Remove(file); } } for (int i = 0; i < _pendingChanges.Count; i++) { br.Tick(); PendingChange pc = _pendingChanges[i]; if (mapped.Contains(pc.FullPath)) { continue; } _pendingChanges.RemoveAt(i--); } } }