diff --git a/lib/18.0/Microsoft.TeamFoundation.Client.dll b/lib/18.0/Microsoft.TeamFoundation.Client.dll
new file mode 100644
index 0000000..e3ccd35
Binary files /dev/null and b/lib/18.0/Microsoft.TeamFoundation.Client.dll differ
diff --git a/lib/18.0/Microsoft.TeamFoundation.Common.dll b/lib/18.0/Microsoft.TeamFoundation.Common.dll
new file mode 100644
index 0000000..d3a0d35
Binary files /dev/null and b/lib/18.0/Microsoft.TeamFoundation.Common.dll differ
diff --git a/lib/18.0/Microsoft.TeamFoundation.Controls.dll b/lib/18.0/Microsoft.TeamFoundation.Controls.dll
new file mode 100644
index 0000000..1c5d7b9
Binary files /dev/null and b/lib/18.0/Microsoft.TeamFoundation.Controls.dll differ
diff --git a/lib/18.0/Microsoft.TeamFoundation.Core.WebApi.dll b/lib/18.0/Microsoft.TeamFoundation.Core.WebApi.dll
new file mode 100644
index 0000000..229480e
Binary files /dev/null and b/lib/18.0/Microsoft.TeamFoundation.Core.WebApi.dll differ
diff --git a/lib/18.0/Microsoft.TeamFoundation.VersionControl.Client.dll b/lib/18.0/Microsoft.TeamFoundation.VersionControl.Client.dll
new file mode 100644
index 0000000..50793ea
Binary files /dev/null and b/lib/18.0/Microsoft.TeamFoundation.VersionControl.Client.dll differ
diff --git a/lib/18.0/Microsoft.TeamFoundation.VersionControl.Common.dll b/lib/18.0/Microsoft.TeamFoundation.VersionControl.Common.dll
new file mode 100644
index 0000000..b28ef40
Binary files /dev/null and b/lib/18.0/Microsoft.TeamFoundation.VersionControl.Common.dll differ
diff --git a/lib/18.0/Microsoft.TeamFoundation.WorkItemTracking.Client.dll b/lib/18.0/Microsoft.TeamFoundation.WorkItemTracking.Client.dll
new file mode 100644
index 0000000..1e20c15
Binary files /dev/null and b/lib/18.0/Microsoft.TeamFoundation.WorkItemTracking.Client.dll differ
diff --git a/lib/18.0/Microsoft.VisualStudio.Services.Client.Interactive.dll b/lib/18.0/Microsoft.VisualStudio.Services.Client.Interactive.dll
new file mode 100644
index 0000000..7e8e968
Binary files /dev/null and b/lib/18.0/Microsoft.VisualStudio.Services.Client.Interactive.dll differ
diff --git a/lib/18.0/Microsoft.VisualStudio.Services.Common.dll b/lib/18.0/Microsoft.VisualStudio.Services.Common.dll
new file mode 100644
index 0000000..b8c2c75
Binary files /dev/null and b/lib/18.0/Microsoft.VisualStudio.Services.Common.dll differ
diff --git a/lib/18.0/Microsoft.VisualStudio.Services.WebApi.dll b/lib/18.0/Microsoft.VisualStudio.Services.WebApi.dll
new file mode 100644
index 0000000..01ae575
Binary files /dev/null and b/lib/18.0/Microsoft.VisualStudio.Services.WebApi.dll differ
diff --git a/lib/18.0/Newtonsoft.Json.dll b/lib/18.0/Newtonsoft.Json.dll
new file mode 100644
index 0000000..62b57c1
Binary files /dev/null and b/lib/18.0/Newtonsoft.Json.dll differ
diff --git a/screenshots/standalone-branches-update.png b/screenshots/standalone-branches-update.png
new file mode 100644
index 0000000..cbae2fe
Binary files /dev/null and b/screenshots/standalone-branches-update.png differ
diff --git a/src/.editorconfig b/src/.editorconfig
index 2b3e8aa..fae980d 100644
--- a/src/.editorconfig
+++ b/src/.editorconfig
@@ -5,7 +5,7 @@ root = true
end_of_line = crlf
insert_final_newline = true
indent_style = space
-indent_size = 4
+indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
diff --git a/src/AutoMerge.Standalone/AddChangesetByIdDialog.Designer.cs b/src/AutoMerge.Standalone/AddChangesetByIdDialog.Designer.cs
new file mode 100644
index 0000000..53fa06e
--- /dev/null
+++ b/src/AutoMerge.Standalone/AddChangesetByIdDialog.Designer.cs
@@ -0,0 +1,91 @@
+namespace AutoMerge.Standalone
+{
+ partial class AddChangesetByIdDialog
+ {
+ private System.ComponentModel.IContainer components = null;
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ private void InitializeComponent()
+ {
+ this.label1 = new System.Windows.Forms.Label();
+ this.txtChangesetId = new System.Windows.Forms.TextBox();
+ this.btnOk = new System.Windows.Forms.Button();
+ this.btnCancel = new System.Windows.Forms.Button();
+ this.SuspendLayout();
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(12, 15);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(96, 17);
+ this.label1.TabIndex = 0;
+ this.label1.Text = "Changeset ID:";
+ //
+ // txtChangesetId
+ //
+ this.txtChangesetId.Location = new System.Drawing.Point(114, 12);
+ this.txtChangesetId.Name = "txtChangesetId";
+ this.txtChangesetId.Size = new System.Drawing.Size(200, 24);
+ this.txtChangesetId.TabIndex = 1;
+ //
+ // btnOk
+ //
+ this.btnOk.Location = new System.Drawing.Point(114, 50);
+ this.btnOk.Name = "btnOk";
+ this.btnOk.Size = new System.Drawing.Size(90, 30);
+ this.btnOk.TabIndex = 2;
+ this.btnOk.Text = "OK";
+ this.btnOk.UseVisualStyleBackColor = true;
+ this.btnOk.Click += new System.EventHandler(this.btnOk_Click);
+ //
+ // btnCancel
+ //
+ this.btnCancel.Location = new System.Drawing.Point(224, 50);
+ this.btnCancel.Name = "btnCancel";
+ this.btnCancel.Size = new System.Drawing.Size(90, 30);
+ this.btnCancel.TabIndex = 3;
+ this.btnCancel.Text = "Cancel";
+ this.btnCancel.UseVisualStyleBackColor = true;
+ this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
+ //
+ // AddChangesetByIdDialog
+ //
+ this.AcceptButton = this.btnOk;
+ this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.CancelButton = this.btnCancel;
+ this.ClientSize = new System.Drawing.Size(326, 92);
+ this.Controls.Add(this.btnCancel);
+ this.Controls.Add(this.btnOk);
+ this.Controls.Add(this.txtChangesetId);
+ this.Controls.Add(this.label1);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "AddChangesetByIdDialog";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "Add Changeset By ID";
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.TextBox txtChangesetId;
+ private System.Windows.Forms.Button btnOk;
+ private System.Windows.Forms.Button btnCancel;
+ }
+}
diff --git a/src/AutoMerge.Standalone/AddChangesetByIdDialog.cs b/src/AutoMerge.Standalone/AddChangesetByIdDialog.cs
new file mode 100644
index 0000000..d15973a
--- /dev/null
+++ b/src/AutoMerge.Standalone/AddChangesetByIdDialog.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Windows.Forms;
+
+namespace AutoMerge.Standalone
+{
+ public partial class AddChangesetByIdDialog : Form
+ {
+ public int ChangesetId { get; private set; }
+
+ public AddChangesetByIdDialog()
+ {
+ InitializeComponent();
+ }
+
+ private void btnOk_Click(object sender, EventArgs e)
+ {
+ if (int.TryParse(txtChangesetId.Text, out int id) && id > 0)
+ {
+ ChangesetId = id;
+ DialogResult = DialogResult.OK;
+ Close();
+ }
+ else
+ {
+ MessageBox.Show("Please enter a valid changeset ID.", "Invalid Input", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ }
+ }
+
+ private void btnCancel_Click(object sender, EventArgs e)
+ {
+ DialogResult = DialogResult.Cancel;
+ Close();
+ }
+ }
+}
diff --git a/src/AutoMerge.Standalone/App.config b/src/AutoMerge.Standalone/App.config
new file mode 100644
index 0000000..996fd1e
--- /dev/null
+++ b/src/AutoMerge.Standalone/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/AutoMerge.Standalone/AutoMerge.Standalone.csproj b/src/AutoMerge.Standalone/AutoMerge.Standalone.csproj
new file mode 100644
index 0000000..742bf24
--- /dev/null
+++ b/src/AutoMerge.Standalone/AutoMerge.Standalone.csproj
@@ -0,0 +1,168 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {8B9A3C2D-5F6E-4A1B-9C3D-2E4F5A6B7C8D}
+ WinExe
+ AutoMerge.Standalone
+ AutoMerge.Standalone
+ v4.8
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\..\lib\18.0\Microsoft.TeamFoundation.Core.WebApi.dll
+
+
+ ..\..\lib\18.0\Microsoft.VisualStudio.Services.Client.Interactive.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\..\lib\18.0\Microsoft.TeamFoundation.Client.dll
+ True
+
+
+ ..\..\lib\18.0\Microsoft.TeamFoundation.Common.dll
+ True
+
+
+ ..\..\lib\18.0\Microsoft.TeamFoundation.Controls.dll
+ True
+
+
+ ..\..\lib\18.0\Microsoft.TeamFoundation.VersionControl.Client.dll
+ True
+
+
+ ..\..\lib\18.0\Microsoft.TeamFoundation.VersionControl.Common.dll
+ True
+
+
+ ..\..\lib\18.0\Microsoft.TeamFoundation.WorkItemTracking.Client.dll
+ True
+
+
+ ..\..\lib\18.0\Microsoft.VisualStudio.Services.Common.dll
+ True
+
+
+ ..\..\lib\18.0\Microsoft.VisualStudio.Services.WebApi.dll
+ True
+
+
+ ..\..\lib\18.0\Newtonsoft.Json.dll
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ AddChangesetByIdDialog.cs
+
+
+ UserControl
+
+
+ AutoMergeControl.cs
+
+
+ Form
+
+
+ MainForm.cs
+
+
+
+
+
+
+ AutoMergeControl.cs
+
+
+ MainForm.cs
+ Designer
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
+ {726ED85E-2274-4D95-B822-B2CFE2CE44B9}
+ AutoMerge
+
+
+
+
\ No newline at end of file
diff --git a/src/AutoMerge.Standalone/AutoMergeControl.Designer.cs b/src/AutoMerge.Standalone/AutoMergeControl.Designer.cs
new file mode 100644
index 0000000..91dc59a
--- /dev/null
+++ b/src/AutoMerge.Standalone/AutoMergeControl.Designer.cs
@@ -0,0 +1,327 @@
+namespace AutoMerge.Standalone
+{
+ partial class AutoMergeControl
+ {
+ private System.ComponentModel.IContainer components = null;
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ private void InitializeComponent()
+ {
+ this.splitContainer1 = new System.Windows.Forms.SplitContainer();
+ this.grpChangesets = new System.Windows.Forms.GroupBox();
+ this.lstChangesets = new System.Windows.Forms.ListView();
+ this.colChangesetId = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.colBranch = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.colComment = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.panel2 = new System.Windows.Forms.Panel();
+ this.btnAddById = new System.Windows.Forms.Button();
+ this.btnRefresh = new System.Windows.Forms.Button();
+ this.grpBranches = new System.Windows.Forms.GroupBox();
+ this.lstBranches = new System.Windows.Forms.ListView();
+ this.colBranchName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.colType = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.colValidation = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.panel3 = new System.Windows.Forms.Panel();
+ this.cmbMergeMode = new System.Windows.Forms.ComboBox();
+ this.label2 = new System.Windows.Forms.Label();
+ this.btnMerge = new System.Windows.Forms.Button();
+ this.statusStripControl = new System.Windows.Forms.StatusStrip();
+ this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel();
+ this.lblStatus = new System.Windows.Forms.ToolStripStatusLabel();
+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
+ this.splitContainer1.Panel1.SuspendLayout();
+ this.splitContainer1.Panel2.SuspendLayout();
+ this.splitContainer1.SuspendLayout();
+ this.grpChangesets.SuspendLayout();
+ this.panel2.SuspendLayout();
+ this.grpBranches.SuspendLayout();
+ this.panel3.SuspendLayout();
+ this.statusStripControl.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // splitContainer1
+ //
+ this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.splitContainer1.Location = new System.Drawing.Point(0, 0);
+ this.splitContainer1.Margin = new System.Windows.Forms.Padding(2);
+ this.splitContainer1.Name = "splitContainer1";
+ this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal;
+ //
+ // splitContainer1.Panel1
+ //
+ this.splitContainer1.Panel1.Controls.Add(this.grpChangesets);
+ //
+ // splitContainer1.Panel2
+ //
+ this.splitContainer1.Panel2.Controls.Add(this.grpBranches);
+ this.splitContainer1.Size = new System.Drawing.Size(700, 539);
+ this.splitContainer1.SplitterDistance = 232;
+ this.splitContainer1.SplitterWidth = 3;
+ this.splitContainer1.TabIndex = 0;
+ //
+ // grpChangesets
+ //
+ this.grpChangesets.Controls.Add(this.lstChangesets);
+ this.grpChangesets.Controls.Add(this.panel2);
+ this.grpChangesets.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.grpChangesets.Location = new System.Drawing.Point(0, 0);
+ this.grpChangesets.Margin = new System.Windows.Forms.Padding(2);
+ this.grpChangesets.Name = "grpChangesets";
+ this.grpChangesets.Padding = new System.Windows.Forms.Padding(2);
+ this.grpChangesets.Size = new System.Drawing.Size(700, 232);
+ this.grpChangesets.TabIndex = 0;
+ this.grpChangesets.TabStop = false;
+ this.grpChangesets.Text = "Recent Changesets";
+ //
+ // lstChangesets
+ //
+ this.lstChangesets.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this.colChangesetId,
+ this.colBranch,
+ this.colComment});
+ this.lstChangesets.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.lstChangesets.FullRowSelect = true;
+ this.lstChangesets.HideSelection = false;
+ this.lstChangesets.Location = new System.Drawing.Point(2, 51);
+ this.lstChangesets.Margin = new System.Windows.Forms.Padding(2);
+ this.lstChangesets.MultiSelect = false;
+ this.lstChangesets.Name = "lstChangesets";
+ this.lstChangesets.Size = new System.Drawing.Size(696, 179);
+ this.lstChangesets.TabIndex = 0;
+ this.lstChangesets.UseCompatibleStateImageBehavior = false;
+ this.lstChangesets.View = System.Windows.Forms.View.Details;
+ this.lstChangesets.SelectedIndexChanged += new System.EventHandler(this.lstChangesets_SelectedIndexChanged);
+ //
+ // colChangesetId
+ //
+ this.colChangesetId.Text = "ID";
+ this.colChangesetId.Width = 80;
+ //
+ // colBranch
+ //
+ this.colBranch.Text = "Branch";
+ this.colBranch.Width = 150;
+ //
+ // colComment
+ //
+ this.colComment.Text = "Comment";
+ this.colComment.Width = 550;
+ //
+ // panel2
+ //
+ this.panel2.Controls.Add(this.btnAddById);
+ this.panel2.Controls.Add(this.btnRefresh);
+ this.panel2.Dock = System.Windows.Forms.DockStyle.Top;
+ this.panel2.Location = new System.Drawing.Point(2, 18);
+ this.panel2.Margin = new System.Windows.Forms.Padding(2);
+ this.panel2.Name = "panel2";
+ this.panel2.Size = new System.Drawing.Size(696, 33);
+ this.panel2.TabIndex = 1;
+ //
+ // btnAddById
+ //
+ this.btnAddById.Location = new System.Drawing.Point(88, 6);
+ this.btnAddById.Margin = new System.Windows.Forms.Padding(2);
+ this.btnAddById.Name = "btnAddById";
+ this.btnAddById.Size = new System.Drawing.Size(79, 25);
+ this.btnAddById.TabIndex = 1;
+ this.btnAddById.Text = "Add By Id";
+ this.btnAddById.UseVisualStyleBackColor = true;
+ this.btnAddById.Click += new System.EventHandler(this.btnAddById_Click);
+ //
+ // btnRefresh
+ //
+ this.btnRefresh.Location = new System.Drawing.Point(4, 6);
+ this.btnRefresh.Margin = new System.Windows.Forms.Padding(2);
+ this.btnRefresh.Name = "btnRefresh";
+ this.btnRefresh.Size = new System.Drawing.Size(79, 25);
+ this.btnRefresh.TabIndex = 0;
+ this.btnRefresh.Text = "Refresh";
+ this.btnRefresh.UseVisualStyleBackColor = true;
+ this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click);
+ //
+ // grpBranches
+ //
+ this.grpBranches.Controls.Add(this.lstBranches);
+ this.grpBranches.Controls.Add(this.panel3);
+ this.grpBranches.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.grpBranches.Location = new System.Drawing.Point(0, 0);
+ this.grpBranches.Margin = new System.Windows.Forms.Padding(2);
+ this.grpBranches.Name = "grpBranches";
+ this.grpBranches.Padding = new System.Windows.Forms.Padding(2);
+ this.grpBranches.Size = new System.Drawing.Size(700, 304);
+ this.grpBranches.TabIndex = 0;
+ this.grpBranches.TabStop = false;
+ this.grpBranches.Text = "Branches";
+ //
+ // lstBranches
+ //
+ this.lstBranches.CheckBoxes = true;
+ this.lstBranches.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this.colBranchName,
+ this.colType,
+ this.colValidation});
+ this.lstBranches.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.lstBranches.FullRowSelect = true;
+ this.lstBranches.HideSelection = false;
+ this.lstBranches.Location = new System.Drawing.Point(2, 51);
+ this.lstBranches.Margin = new System.Windows.Forms.Padding(2);
+ this.lstBranches.Name = "lstBranches";
+ this.lstBranches.Size = new System.Drawing.Size(696, 251);
+ this.lstBranches.TabIndex = 0;
+ this.lstBranches.UseCompatibleStateImageBehavior = false;
+ this.lstBranches.View = System.Windows.Forms.View.Details;
+ this.lstBranches.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.lstBranches_ItemCheck);
+ this.lstBranches.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.lstBranches_ItemChecked);
+ this.lstBranches.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(this.lstBranches_ItemSelectionChanged);
+ //
+ // colBranchName
+ //
+ this.colBranchName.Text = "Branch Name";
+ this.colBranchName.Width = 300;
+ //
+ // colType
+ //
+ this.colType.Text = "Type";
+ this.colType.Width = 100;
+ //
+ // colValidation
+ //
+ this.colValidation.Text = "Validation";
+ this.colValidation.Width = 380;
+ //
+ // panel3
+ //
+ this.panel3.Controls.Add(this.cmbMergeMode);
+ this.panel3.Controls.Add(this.label2);
+ this.panel3.Controls.Add(this.btnMerge);
+ this.panel3.Dock = System.Windows.Forms.DockStyle.Top;
+ this.panel3.Location = new System.Drawing.Point(2, 18);
+ this.panel3.Margin = new System.Windows.Forms.Padding(2);
+ this.panel3.Name = "panel3";
+ this.panel3.Size = new System.Drawing.Size(696, 33);
+ this.panel3.TabIndex = 1;
+ //
+ // cmbMergeMode
+ //
+ this.cmbMergeMode.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.cmbMergeMode.FormattingEnabled = true;
+ this.cmbMergeMode.Items.AddRange(new object[] {
+ "Merge",
+ "Merge and Check In"});
+ this.cmbMergeMode.Location = new System.Drawing.Point(175, 7);
+ this.cmbMergeMode.Margin = new System.Windows.Forms.Padding(2);
+ this.cmbMergeMode.Name = "cmbMergeMode";
+ this.cmbMergeMode.Size = new System.Drawing.Size(132, 23);
+ this.cmbMergeMode.TabIndex = 2;
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(91, 10);
+ this.label2.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(78, 15);
+ this.label2.TabIndex = 1;
+ this.label2.Text = "Merge Mode:";
+ //
+ // btnMerge
+ //
+ this.btnMerge.Enabled = false;
+ this.btnMerge.Location = new System.Drawing.Point(4, 6);
+ this.btnMerge.Margin = new System.Windows.Forms.Padding(2);
+ this.btnMerge.Name = "btnMerge";
+ this.btnMerge.Size = new System.Drawing.Size(79, 25);
+ this.btnMerge.TabIndex = 0;
+ this.btnMerge.Text = "Merge";
+ this.btnMerge.UseVisualStyleBackColor = true;
+ this.btnMerge.Click += new System.EventHandler(this.btnMerge_Click);
+ //
+ // statusStripControl
+ //
+ this.statusStripControl.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.toolStripStatusLabel1,
+ this.lblStatus});
+ this.statusStripControl.Location = new System.Drawing.Point(0, 539);
+ this.statusStripControl.Name = "statusStripControl";
+ this.statusStripControl.Padding = new System.Windows.Forms.Padding(1, 0, 12, 0);
+ this.statusStripControl.Size = new System.Drawing.Size(700, 24);
+ this.statusStripControl.TabIndex = 1;
+ this.statusStripControl.Text = "statusStripControl";
+ //
+ // toolStripStatusLabel1
+ //
+ this.toolStripStatusLabel1.Name = "toolStripStatusLabel1";
+ this.toolStripStatusLabel1.Padding = new System.Windows.Forms.Padding(0, 0, 10, 0);
+ this.toolStripStatusLabel1.Size = new System.Drawing.Size(128, 19);
+ this.toolStripStatusLabel1.Text = "toolStripStatusLabel1";
+ //
+ // lblStatus
+ //
+ this.lblStatus.BorderSides = System.Windows.Forms.ToolStripStatusLabelBorderSides.Left;
+ this.lblStatus.Name = "lblStatus";
+ this.lblStatus.Padding = new System.Windows.Forms.Padding(10, 0, 0, 0);
+ this.lblStatus.Size = new System.Drawing.Size(53, 19);
+ this.lblStatus.Text = "Ready";
+ //
+ // AutoMergeControl
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.splitContainer1);
+ this.Controls.Add(this.statusStripControl);
+ this.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.Margin = new System.Windows.Forms.Padding(2);
+ this.Name = "AutoMergeControl";
+ this.Size = new System.Drawing.Size(700, 563);
+ this.splitContainer1.Panel1.ResumeLayout(false);
+ this.splitContainer1.Panel2.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
+ this.splitContainer1.ResumeLayout(false);
+ this.grpChangesets.ResumeLayout(false);
+ this.panel2.ResumeLayout(false);
+ this.grpBranches.ResumeLayout(false);
+ this.panel3.ResumeLayout(false);
+ this.panel3.PerformLayout();
+ this.statusStripControl.ResumeLayout(false);
+ this.statusStripControl.PerformLayout();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.SplitContainer splitContainer1;
+ private System.Windows.Forms.GroupBox grpChangesets;
+ private System.Windows.Forms.ListView lstChangesets;
+ private System.Windows.Forms.ColumnHeader colChangesetId;
+ private System.Windows.Forms.ColumnHeader colBranch;
+ private System.Windows.Forms.ColumnHeader colComment;
+ private System.Windows.Forms.Panel panel2;
+ private System.Windows.Forms.Button btnRefresh;
+ private System.Windows.Forms.GroupBox grpBranches;
+ private System.Windows.Forms.ListView lstBranches;
+ private System.Windows.Forms.ColumnHeader colBranchName;
+ private System.Windows.Forms.ColumnHeader colType;
+ private System.Windows.Forms.ColumnHeader colValidation;
+ private System.Windows.Forms.Panel panel3;
+ private System.Windows.Forms.Button btnMerge;
+ private System.Windows.Forms.StatusStrip statusStripControl;
+ private System.Windows.Forms.ToolStripStatusLabel lblStatus;
+ private System.Windows.Forms.Button btnAddById;
+ private System.Windows.Forms.ComboBox cmbMergeMode;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1;
+ }
+}
diff --git a/src/AutoMerge.Standalone/AutoMergeControl.cs b/src/AutoMerge.Standalone/AutoMergeControl.cs
new file mode 100644
index 0000000..9a0dd5d
--- /dev/null
+++ b/src/AutoMerge.Standalone/AutoMergeControl.cs
@@ -0,0 +1,300 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using Microsoft.TeamFoundation.Client;
+using Microsoft.TeamFoundation.VersionControl.Client;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement.TreeView;
+
+namespace AutoMerge.Standalone
+{
+ public partial class AutoMergeControl : UserControl
+ {
+ private const string DefaultTeamProjectName = "Intact iQ";
+
+ private StandaloneServiceProvider _serviceProvider;
+ private TfsTeamProjectCollection _tfs;
+ private VersionControlServer _versionControl;
+ private global::AutoMerge.ChangesetService _changesetService;
+ private List _changesets;
+ private int _selectedChangesetId;
+
+ public AutoMergeControl()
+ {
+ InitializeComponent();
+ _changesets = new List();
+ }
+
+ public void Initialize(StandaloneServiceProvider serviceProvider)
+ {
+ _serviceProvider = serviceProvider;
+ _tfs = serviceProvider.TfsConnection;
+ _versionControl = _tfs.GetService();
+ _changesetService = new global::AutoMerge.ChangesetService(_versionControl);
+ cmbMergeMode.SelectedIndex = 0;
+
+ InitializeAsync();
+ }
+
+ public void ConnectedStatusMessage(string message)
+ {
+ toolStripStatusLabel1.Text = message;
+ }
+
+ private async Task InitializeAsync()
+ {
+ try
+ {
+ lblStatus.Text = "Loading changesets...";
+ await LoadRecentChangesetsAsync();
+ lblStatus.Text = "Ready";
+ }
+ catch (Exception ex)
+ {
+ lblStatus.Text = $"Error: {ex.Message}";
+ MessageBox.Show($"Failed to initialize:\n\n{ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ private async Task LoadRecentChangesetsAsync()
+ {
+ var changesetProvider = new global::AutoMerge.MyChangesetChangesetProvider(
+ _changesetService,
+ DefaultTeamProjectName,
+ global::AutoMerge.Settings.Instance.ChangesetCount,
+ true);
+
+ _changesets = await changesetProvider.GetChangesets(_versionControl.AuthorizedUser);
+
+ UpdateChangesetsView();
+ }
+
+ private void UpdateChangesetsView()
+ {
+ lstChangesets.Items.Clear();
+
+ foreach (var changeset in _changesets)
+ {
+ var item = new ListViewItem(changeset.ChangesetId.ToString());
+
+ item.SubItems.Add("");
+
+ item.SubItems.Add(TruncateComment(changeset.Comment) + (string.IsNullOrWhiteSpace(changeset.DisplayBranchName) ? string.Empty : $" [{changeset.DisplayBranchName}]"));
+
+ item.Tag = changeset;
+
+ lstChangesets.Items.Add(item);
+ }
+
+ if (lstChangesets.Items.Count > 0)
+ {
+ lstChangesets.Items[0].Selected = true;
+ }
+ }
+
+ private async Task UpdateBranchesViewAsync()
+ {
+ try
+ {
+ lstBranches.Items.Clear();
+
+ lblStatus.Text = $"Loading branches for changeset {_selectedChangesetId}...";
+
+ var selectedChangeset = lstChangesets.SelectedItems.Count > 0
+ ? lstChangesets.SelectedItems[0].Tag as global::AutoMerge.ChangesetViewModel
+ : null;
+
+ if (selectedChangeset != null)
+ {
+ var workspaces = _versionControl.QueryWorkspaces(null, _tfs.AuthorizedIdentity.UniqueName, Environment.MachineName);
+ var workspace = workspaces.Length == 0
+ ? null
+ : global::AutoMerge.WorkspaceHelper.GetWorkspace(_versionControl, workspaces);
+
+ if (workspace != null)
+ {
+ var branches = await Task.Run(() =>
+ global::AutoMerge.BranchesViewModel.GetBranches(
+ _tfs,
+ selectedChangeset,
+ workspace,
+ _changesetService,
+ new global::AutoMerge.Prism.Events.EventAggregator()));
+
+ foreach (var branch in branches)
+ {
+ var branchText = branch.DisplayBranchName;
+
+ var type = "Target";
+
+ if (branch.IsSourceBranch)
+ {
+ continue; // TODO_DS1 Skip source branches for now, as they can't be merged to
+ //branchText += " (source)";
+ //type = "Source";
+ }
+
+ var item = new ListViewItem(branchText) { Checked = !branch.IsSourceBranch && branch.Checked };
+
+ item.SubItems.Add(type);
+
+ item.SubItems.Add(branch.ValidationMessage ?? string.Empty);
+
+ item.Tag = branch;
+
+ if (branch.ValidationResult != BranchValidationResult.Success)
+ {
+ item.ForeColor = System.Drawing.Color.Gray;
+ }
+
+ lstBranches.Items.Add(item);
+ }
+ }
+ else
+ {
+ lblStatus.Text = "No workspace found. Create/map a TFVC workspace and refresh.";
+ }
+ }
+
+ UpdateMergeButton();
+
+ if (lblStatus.Text != "No workspace found. Create/map a TFVC workspace and refresh.")
+ {
+ lblStatus.Text = "Ready";
+ }
+ }
+ catch (Exception ex)
+ {
+ System.Diagnostics.Debug.WriteLine(ex);
+ lblStatus.Text = "Error loading branches";
+ MessageBox.Show($"Failed to load branches:\n\n{ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ private string TruncateComment(string comment)
+ {
+ if (string.IsNullOrEmpty(comment))
+ return "";
+
+ var firstLine = comment.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault() ?? "";
+ return firstLine.Length > 80 ? firstLine.Substring(0, 77) + "..." : firstLine;
+ }
+
+ private async void lstChangesets_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ if (lstChangesets.SelectedItems.Count > 0)
+ {
+ var changeset = lstChangesets.SelectedItems[0].Tag as global::AutoMerge.ChangesetViewModel;
+
+ if (changeset != null)
+ {
+ _selectedChangesetId = changeset.ChangesetId;
+
+ await UpdateBranchesViewAsync();
+ }
+ }
+ }
+
+ private void lstBranches_ItemChecked(object sender, ItemCheckedEventArgs e)
+ {
+ UpdateMergeButton();
+ }
+
+ private void lstBranches_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
+ {
+ if (e.Item.Tag is MergeInfoViewModel branch)
+ {
+ if (branch.ValidationResult != BranchValidationResult.Success)
+ e.Item.Selected = false;
+ }
+ }
+
+ private void lstBranches_ItemCheck(object sender, ItemCheckEventArgs e)
+ {
+ if (lstBranches.Items[e.Index].Tag is MergeInfoViewModel branch)
+ {
+ if (branch.ValidationResult != BranchValidationResult.Success)
+ e.NewValue = e.CurrentValue;
+ }
+ }
+
+ private void UpdateMergeButton()
+ {
+ btnMerge.Enabled = lstBranches.CheckedItems.Count > 0;
+ }
+
+ private async void btnMerge_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ btnMerge.Enabled = false;
+ lblStatus.Text = "Merging...";
+
+ // TODO_DS1 Placeholder for merge operation
+ await Task.Delay(1000);
+
+ lblStatus.Text = "Merge completed";
+ MessageBox.Show("Merge operation completed successfully.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ }
+ catch (Exception ex)
+ {
+ lblStatus.Text = "Merge failed";
+ MessageBox.Show($"Merge failed:\n\n{ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ finally
+ {
+ btnMerge.Enabled = true;
+ }
+ }
+
+ private void btnRefresh_Click(object sender, EventArgs e)
+ {
+ InitializeAsync();
+ }
+
+ private void btnAddById_Click(object sender, EventArgs e)
+ {
+ using (var form = new AddChangesetByIdDialog())
+ {
+ if (form.ShowDialog() == DialogResult.OK)
+ {
+ var changesetId = form.ChangesetId;
+ AddChangesetByIdAsync(changesetId);
+ }
+ }
+ }
+
+ private async void AddChangesetByIdAsync(int changesetId)
+ {
+ try
+ {
+ lblStatus.Text = $"Loading changeset {changesetId}...";
+
+ var changesetProvider = new global::AutoMerge.ChangesetByIdChangesetProvider(_changesetService, new[] { changesetId });
+ var changesets = await changesetProvider.GetChangesets(null);
+ if (changesets.Count > 0)
+ {
+ _changesets.Add(changesets[0]);
+ }
+
+ UpdateChangesetsView();
+
+ var items = lstChangesets.Items.Cast()
+ .Where(i => ((global::AutoMerge.ChangesetViewModel)i.Tag).ChangesetId == changesetId).ToArray();
+ if (items.Length > 0)
+ {
+ items[0].Selected = true;
+ items[0].EnsureVisible();
+ }
+
+ lblStatus.Text = "Ready";
+ }
+ catch (Exception ex)
+ {
+ lblStatus.Text = "Error loading changeset";
+ MessageBox.Show($"Failed to load changeset:\n\n{ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+ }
+}
diff --git a/src/AutoMerge.Standalone/AutoMergeControl.resx b/src/AutoMerge.Standalone/AutoMergeControl.resx
new file mode 100644
index 0000000..d6dd895
--- /dev/null
+++ b/src/AutoMerge.Standalone/AutoMergeControl.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/src/AutoMerge.Standalone/MainForm.Designer.cs b/src/AutoMerge.Standalone/MainForm.Designer.cs
new file mode 100644
index 0000000..f4ed8d4
--- /dev/null
+++ b/src/AutoMerge.Standalone/MainForm.Designer.cs
@@ -0,0 +1,134 @@
+namespace AutoMerge.Standalone
+{
+ partial class MainForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.panelContent = new System.Windows.Forms.Panel();
+ this.autoMergeControl1 = new AutoMerge.Standalone.AutoMergeControl();
+ this.panel1 = new System.Windows.Forms.Panel();
+ this.btnConnect = new System.Windows.Forms.Button();
+ this.txtTfsUrl = new System.Windows.Forms.TextBox();
+ this.label1 = new System.Windows.Forms.Label();
+ this.panelContent.SuspendLayout();
+ this.panel1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // panelContent
+ //
+ this.panelContent.Controls.Add(this.autoMergeControl1);
+ this.panelContent.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.panelContent.Location = new System.Drawing.Point(0, 57);
+ this.panelContent.Margin = new System.Windows.Forms.Padding(2);
+ this.panelContent.Name = "panelContent";
+ this.panelContent.Size = new System.Drawing.Size(1469, 625);
+ this.panelContent.TabIndex = 0;
+ //
+ // autoMergeControl1
+ //
+ this.autoMergeControl1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.autoMergeControl1.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.autoMergeControl1.Location = new System.Drawing.Point(0, 0);
+ this.autoMergeControl1.Margin = new System.Windows.Forms.Padding(2);
+ this.autoMergeControl1.Name = "autoMergeControl1";
+ this.autoMergeControl1.Size = new System.Drawing.Size(1469, 625);
+ this.autoMergeControl1.TabIndex = 0;
+ //
+ // panel1
+ //
+ this.panel1.Controls.Add(this.btnConnect);
+ this.panel1.Controls.Add(this.txtTfsUrl);
+ this.panel1.Controls.Add(this.label1);
+ this.panel1.Dock = System.Windows.Forms.DockStyle.Top;
+ this.panel1.Location = new System.Drawing.Point(0, 0);
+ this.panel1.Margin = new System.Windows.Forms.Padding(2);
+ this.panel1.Name = "panel1";
+ this.panel1.Size = new System.Drawing.Size(1469, 57);
+ this.panel1.TabIndex = 1;
+ //
+ // btnConnect
+ //
+ this.btnConnect.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnConnect.Location = new System.Drawing.Point(1381, 17);
+ this.btnConnect.Margin = new System.Windows.Forms.Padding(2);
+ this.btnConnect.Name = "btnConnect";
+ this.btnConnect.Size = new System.Drawing.Size(77, 25);
+ this.btnConnect.TabIndex = 2;
+ this.btnConnect.Text = "Connect";
+ this.btnConnect.UseVisualStyleBackColor = true;
+ this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click);
+ //
+ // txtTfsUrl
+ //
+ this.txtTfsUrl.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.txtTfsUrl.Location = new System.Drawing.Point(79, 18);
+ this.txtTfsUrl.Margin = new System.Windows.Forms.Padding(2);
+ this.txtTfsUrl.Name = "txtTfsUrl";
+ this.txtTfsUrl.Size = new System.Drawing.Size(1294, 23);
+ this.txtTfsUrl.TabIndex = 1;
+ this.txtTfsUrl.Text = "https://devops.intactsoftware.com/tfs";
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(10, 22);
+ this.label1.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(53, 15);
+ this.label1.TabIndex = 0;
+ this.label1.Text = "TFS URL:";
+ //
+ // MainForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(1469, 682);
+ this.Controls.Add(this.panelContent);
+ this.Controls.Add(this.panel1);
+ this.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.Margin = new System.Windows.Forms.Padding(2);
+ this.Name = "MainForm";
+ this.Text = "AutoMerge - Standalone";
+ this.Load += new System.EventHandler(this.MainForm_Load);
+ this.panelContent.ResumeLayout(false);
+ this.panel1.ResumeLayout(false);
+ this.panel1.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Panel panelContent;
+ private System.Windows.Forms.Panel panel1;
+ private System.Windows.Forms.Button btnConnect;
+ private System.Windows.Forms.TextBox txtTfsUrl;
+ private System.Windows.Forms.Label label1;
+ private AutoMergeControl autoMergeControl1;
+ }
+}
diff --git a/src/AutoMerge.Standalone/MainForm.cs b/src/AutoMerge.Standalone/MainForm.cs
new file mode 100644
index 0000000..5508e8a
--- /dev/null
+++ b/src/AutoMerge.Standalone/MainForm.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Windows.Forms;
+
+namespace AutoMerge.Standalone
+{
+ public partial class MainForm : Form
+ {
+ private StandaloneServiceProvider _serviceProvider;
+ //TODO_DS1 private AutoMergeControl _autoMergeControl;
+
+ public MainForm()
+ {
+ InitializeComponent();
+ }
+
+ private void btnConnect_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ btnConnect.Enabled = false;
+ autoMergeControl1.ConnectedStatusMessage("Connecting...");
+ //TODO_DS1 toolStripStatusLabel1.Text = "Connecting...";
+ Application.DoEvents();
+
+ // Create service provider with TFS connection
+ _serviceProvider = new StandaloneServiceProvider(txtTfsUrl.Text);
+
+ //// TODO_DS1 Create the AutoMerge WinForms control
+ //_autoMergeControl = new AutoMergeControl();
+ //_autoMergeControl.Dock = DockStyle.Fill;
+
+ //// TODO_DS1 Add it to the panel
+ //panelContent.Controls.Clear();
+ //panelContent.Controls.Add(_autoMergeControl);
+
+ // Initialize the control
+ autoMergeControl1.Initialize(_serviceProvider);
+
+ autoMergeControl1.ConnectedStatusMessage($"Connected to {txtTfsUrl.Text}");
+
+ //TODO_DS1 toolStripStatusLabel1.Text = $"Connected to {txtTfsUrl.Text}";
+ txtTfsUrl.Enabled = false;
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(
+ $"Failed to connect to TFS:\n\n{ex.Message}",
+ "Connection Error",
+ MessageBoxButtons.OK,
+ MessageBoxIcon.Error);
+
+ autoMergeControl1.ConnectedStatusMessage("Connection failed");
+ //TODO_DS1 toolStripStatusLabel1.Text = "Connection failed";
+ btnConnect.Enabled = true;
+ }
+ }
+
+ // TODO_DS1 Change this to be an auto connect, no need for the button and txtbox
+ private void MainForm_Load(object sender, EventArgs e)
+ {
+ btnConnect_Click(null, EventArgs.Empty);
+ }
+ }
+}
diff --git a/src/AutoMerge.Standalone/MainForm.resx b/src/AutoMerge.Standalone/MainForm.resx
new file mode 100644
index 0000000..d58980a
--- /dev/null
+++ b/src/AutoMerge.Standalone/MainForm.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/src/AutoMerge.Standalone/Program.cs b/src/AutoMerge.Standalone/Program.cs
new file mode 100644
index 0000000..e008ddf
--- /dev/null
+++ b/src/AutoMerge.Standalone/Program.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Windows.Forms;
+
+namespace AutoMerge.Standalone
+{
+ static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new MainForm());
+ }
+ }
+}
diff --git a/src/AutoMerge.Standalone/Properties/AssemblyInfo.cs b/src/AutoMerge.Standalone/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..be6645b
--- /dev/null
+++ b/src/AutoMerge.Standalone/Properties/AssemblyInfo.cs
@@ -0,0 +1,19 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("AutoMerge.Standalone")]
+[assembly: AssemblyDescription("Standalone AutoMerge application for TFS")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("AutoMerge.Standalone")]
+[assembly: AssemblyCopyright("Copyright © 2025")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: ComVisible(false)]
+
+[assembly: Guid("8b9a3c2d-5f6e-4a1b-9c3d-2e4f5a6b7c8d")]
+
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/AutoMerge.Standalone/Properties/Resources.Designer.cs b/src/AutoMerge.Standalone/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..6a81269
--- /dev/null
+++ b/src/AutoMerge.Standalone/Properties/Resources.Designer.cs
@@ -0,0 +1,47 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace AutoMerge.Standalone.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Resources : global::System.Resources.ResourceManager {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoMerge.Standalone.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/src/AutoMerge.Standalone/Properties/Resources.resx b/src/AutoMerge.Standalone/Properties/Resources.resx
new file mode 100644
index 0000000..1510323
--- /dev/null
+++ b/src/AutoMerge.Standalone/Properties/Resources.resx
@@ -0,0 +1,15 @@
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
diff --git a/src/AutoMerge.Standalone/Properties/Settings.Designer.cs b/src/AutoMerge.Standalone/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..cb80298
--- /dev/null
+++ b/src/AutoMerge.Standalone/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace AutoMerge.Standalone.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/src/AutoMerge.Standalone/Properties/Settings.settings b/src/AutoMerge.Standalone/Properties/Settings.settings
new file mode 100644
index 0000000..07e66be
--- /dev/null
+++ b/src/AutoMerge.Standalone/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/src/AutoMerge.Standalone/README.md b/src/AutoMerge.Standalone/README.md
new file mode 100644
index 0000000..6ca93c8
--- /dev/null
+++ b/src/AutoMerge.Standalone/README.md
@@ -0,0 +1,75 @@
+# AutoMerge - Setup Complete
+
+## Summary of Changes
+
+### 1. Fixed AutoMergeToolWindowControl
+**Problem**: The tool window wasn't loading changesets or branch data.
+
+**Solution**: Modified `AutoMergeToolWindowControl.xaml.cs` to properly initialize the ViewModels:
+- Added calls to `Initialize()` with `SectionInitializeEventArgs`
+- Added calls to `Refresh()` to trigger data loading
+- Kept error handling to show detailed error messages if initialization fails
+
+The ViewModels (`RecentChangesetsViewModel` and `BranchesViewModel`) inherit from `TeamExplorerSectionViewModelBase` which requires proper initialization before they will load data.
+
+### 2. Created Standalone WinForms Application
+**New Project**: `AutoMerge.Standalone`
+
+A standalone Windows Forms application that can run the AutoMerge functionality outside of Visual Studio.
+
+**Key Files Created**:
+- `AutoMerge.Standalone.csproj` - Project file targeting .NET Framework 4.8
+- `Program.cs` - Application entry point
+- `MainForm.cs/Designer.cs` - Main form with TFS connection UI
+- `StandaloneServiceProvider.cs` - Service provider for TFS connectivity
+- `StandaloneLogger.cs` - Console/Debug logger implementation
+
+**Features**:
+- Connect to any TFS server by entering the URL
+- Hosts the AutoMerge WPF control using ElementHost
+- Shows connection status in status bar
+- Reuses all the existing AutoMerge logic from the VSIX project
+
+**How to Use**:
+1. Build the solution
+2. Run `AutoMerge.Standalone.exe`
+3. Enter your TFS URL (e.g., `http://your-tfs-server:8080/tfs/DefaultCollection`)
+4. Click "Connect"
+5. The AutoMerge interface will load with Recent Changesets and Branches sections
+
+### 3. Dependencies
+Both projects now reference the correct VS 2026 TeamFoundation assemblies:
+- Microsoft.TeamFoundation.Client (v20.256.x)
+- Microsoft.TeamFoundation.Common (v20.256.x)
+- Microsoft.TeamFoundation.Controls (v18.5.x)
+- Microsoft.TeamFoundation.VersionControl.Client (v20.256.x)
+- Microsoft.TeamFoundation.VersionControl.Common (v20.256.x)
+- Microsoft.TeamFoundation.WorkItemTracking.Client (v20.256.x)
+- Microsoft.VisualStudio.Services.Common
+- Microsoft.VisualStudio.Services.WebApi
+- Newtonsoft.Json
+
+All assemblies are set to `Private=True` so they are packaged with the applications.
+
+## Testing the VSIX
+
+1. Press **F5** in Visual Studio
+2. A new VS instance will launch (experimental)
+3. Open a solution connected to TFS
+4. Go to **View > Other Windows > AutoMerge Tool Window** OR
+5. Use the Team Explorer button
+6. The window should now show your recent changesets and branches
+
+## Testing the Standalone App
+
+1. Set `AutoMerge.Standalone` as the startup project
+2. Press **F5** or **Ctrl+F5**
+3. Enter your TFS server URL
+4. Click Connect
+5. The AutoMerge interface should load
+
+## Notes
+
+- The standalone app requires access to a TFS server
+- You may need to adjust the `StandaloneServiceProvider` if additional services are needed
+- The standalone app uses the same ViewModels and Views as the VSIX, ensuring consistent behavior
diff --git a/src/AutoMerge.Standalone/StandaloneLogger.cs b/src/AutoMerge.Standalone/StandaloneLogger.cs
new file mode 100644
index 0000000..349b636
--- /dev/null
+++ b/src/AutoMerge.Standalone/StandaloneLogger.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace AutoMerge
+{
+ ///
+ /// Standalone logger implementation that writes to console or debug output
+ ///
+ public class StandaloneLogger : LoggerBase
+ {
+ protected override void WriteMessage(string message)
+ {
+ System.Diagnostics.Debug.WriteLine(message);
+ Console.WriteLine(message);
+ }
+ }
+}
diff --git a/src/AutoMerge.Standalone/StandaloneServiceProvider.cs b/src/AutoMerge.Standalone/StandaloneServiceProvider.cs
new file mode 100644
index 0000000..c2da9cf
--- /dev/null
+++ b/src/AutoMerge.Standalone/StandaloneServiceProvider.cs
@@ -0,0 +1,33 @@
+using System;
+using Microsoft.TeamFoundation.Client;
+
+namespace AutoMerge.Standalone
+{
+ ///
+ /// Minimal service provider for standalone operation
+ ///
+ public class StandaloneServiceProvider : IServiceProvider
+ {
+ private readonly TfsTeamProjectCollection _tfsConnection;
+
+ public StandaloneServiceProvider(string tfsUrl)
+ {
+ _tfsConnection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(tfsUrl));
+ _tfsConnection.EnsureAuthenticated();
+ }
+
+ public object GetService(Type serviceType)
+ {
+ // Return the TFS connection for TFS-related services
+ if (serviceType == typeof(TfsTeamProjectCollection))
+ {
+ return _tfsConnection;
+ }
+
+ // Add more service mappings as needed
+ return null;
+ }
+
+ public TfsTeamProjectCollection TfsConnection => _tfsConnection;
+ }
+}
diff --git a/src/AutoMerge.sln b/src/AutoMerge.sln
index de6d2cd..9f4586a 100644
--- a/src/AutoMerge.sln
+++ b/src/AutoMerge.sln
@@ -1,16 +1,89 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.0.32112.339
+# Visual Studio Version 18
+VisualStudioVersion = 18.5.11723.231
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoMerge", "AutoMerge\AutoMerge.csproj", "{726ED85E-2274-4D95-B822-B2CFE2CE44B9}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{5101B5A3-BBBF-474C-8BBF-A61EF46643D0}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "15.0", "15.0", "{6C80EF52-0D76-4F42-A66C-B18B1477A8CE}"
+ ProjectSection(SolutionItems) = preProject
+ ..\lib\15.0\Microsoft.TeamFoundation.Client.dll = ..\lib\15.0\Microsoft.TeamFoundation.Client.dll
+ ..\lib\15.0\Microsoft.TeamFoundation.Common.dll = ..\lib\15.0\Microsoft.TeamFoundation.Common.dll
+ ..\lib\15.0\Microsoft.TeamFoundation.Controls.dll = ..\lib\15.0\Microsoft.TeamFoundation.Controls.dll
+ ..\lib\15.0\Microsoft.TeamFoundation.VersionControl.Client.dll = ..\lib\15.0\Microsoft.TeamFoundation.VersionControl.Client.dll
+ ..\lib\15.0\Microsoft.TeamFoundation.VersionControl.Common.dll = ..\lib\15.0\Microsoft.TeamFoundation.VersionControl.Common.dll
+ ..\lib\15.0\Microsoft.TeamFoundation.WorkItemTracking.Client.dll = ..\lib\15.0\Microsoft.TeamFoundation.WorkItemTracking.Client.dll
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "16.0", "16.0", "{067032CB-986B-4AD8-A3E1-5AE11C544A47}"
+ ProjectSection(SolutionItems) = preProject
+ ..\lib\16.0\Microsoft.TeamFoundation.Client.dll = ..\lib\16.0\Microsoft.TeamFoundation.Client.dll
+ ..\lib\16.0\Microsoft.TeamFoundation.Common.dll = ..\lib\16.0\Microsoft.TeamFoundation.Common.dll
+ ..\lib\16.0\Microsoft.TeamFoundation.Controls.dll = ..\lib\16.0\Microsoft.TeamFoundation.Controls.dll
+ ..\lib\16.0\Microsoft.TeamFoundation.VersionControl.Client.dll = ..\lib\16.0\Microsoft.TeamFoundation.VersionControl.Client.dll
+ ..\lib\16.0\Microsoft.TeamFoundation.VersionControl.Common.dll = ..\lib\16.0\Microsoft.TeamFoundation.VersionControl.Common.dll
+ ..\lib\16.0\Microsoft.TeamFoundation.WorkItemTracking.Client.dll = ..\lib\16.0\Microsoft.TeamFoundation.WorkItemTracking.Client.dll
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "17.0", "17.0", "{5DC7FDC7-5BF6-4C05-A817-72C9C8546090}"
+ ProjectSection(SolutionItems) = preProject
+ ..\lib\17.0\Microsoft.TeamFoundation.Client.dll = ..\lib\17.0\Microsoft.TeamFoundation.Client.dll
+ ..\lib\17.0\Microsoft.TeamFoundation.Common.dll = ..\lib\17.0\Microsoft.TeamFoundation.Common.dll
+ ..\lib\17.0\Microsoft.TeamFoundation.Controls.dll = ..\lib\17.0\Microsoft.TeamFoundation.Controls.dll
+ ..\lib\17.0\Microsoft.TeamFoundation.VersionControl.Client.dll = ..\lib\17.0\Microsoft.TeamFoundation.VersionControl.Client.dll
+ ..\lib\17.0\Microsoft.TeamFoundation.VersionControl.Common.dll = ..\lib\17.0\Microsoft.TeamFoundation.VersionControl.Common.dll
+ ..\lib\17.0\Microsoft.TeamFoundation.WorkItemTracking.Client.dll = ..\lib\17.0\Microsoft.TeamFoundation.WorkItemTracking.Client.dll
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "18.0", "18.0", "{2286A832-B2F8-45AE-933A-0A855E5AD542}"
+ ProjectSection(SolutionItems) = preProject
+ ..\lib\18.0\Microsoft.TeamFoundation.Client.dll = ..\lib\18.0\Microsoft.TeamFoundation.Client.dll
+ ..\lib\18.0\Microsoft.TeamFoundation.Common.dll = ..\lib\18.0\Microsoft.TeamFoundation.Common.dll
+ ..\lib\18.0\Microsoft.TeamFoundation.Controls.dll = ..\lib\18.0\Microsoft.TeamFoundation.Controls.dll
+ ..\lib\18.0\Microsoft.TeamFoundation.Core.WebApi.dll = ..\lib\18.0\Microsoft.TeamFoundation.Core.WebApi.dll
+ ..\lib\18.0\Microsoft.TeamFoundation.VersionControl.Client.dll = ..\lib\18.0\Microsoft.TeamFoundation.VersionControl.Client.dll
+ ..\lib\18.0\Microsoft.TeamFoundation.VersionControl.Common.dll = ..\lib\18.0\Microsoft.TeamFoundation.VersionControl.Common.dll
+ ..\lib\18.0\Microsoft.TeamFoundation.WorkItemTracking.Client.dll = ..\lib\18.0\Microsoft.TeamFoundation.WorkItemTracking.Client.dll
+ ..\lib\18.0\Microsoft.VisualStudio.Services.Client.Interactive.dll = ..\lib\18.0\Microsoft.VisualStudio.Services.Client.Interactive.dll
+ ..\lib\18.0\Microsoft.VisualStudio.Services.Common.dll = ..\lib\18.0\Microsoft.VisualStudio.Services.Common.dll
+ ..\lib\18.0\Microsoft.VisualStudio.Services.WebApi.dll = ..\lib\18.0\Microsoft.VisualStudio.Services.WebApi.dll
+ ..\lib\18.0\Newtonsoft.Json.dll = ..\lib\18.0\Newtonsoft.Json.dll
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8FE189FF-6AED-444C-B5DE-9F841281B0F9}"
+ ProjectSection(SolutionItems) = preProject
+ ..\.gitignore = ..\.gitignore
+ ..\azure-pipelines.yml = ..\azure-pipelines.yml
+ ..\build_v15.bat = ..\build_v15.bat
+ ..\build_v16.bat = ..\build_v16.bat
+ ..\build_v17.bat = ..\build_v17.bat
+ ..\LICENSE.txt = ..\LICENSE.txt
+ ..\README.md = ..\README.md
+ ..\RELEASE_NOTES.md = ..\RELEASE_NOTES.md
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{D5AD1EB1-1B80-450D-92E2-C6FECB556576}"
+ ProjectSection(SolutionItems) = preProject
+ ..\build\build.fsx = ..\build\build.fsx
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "screenshots", "screenshots", "{A2F06608-443F-4923-8E3B-3BC7E7E40A53}"
+ ProjectSection(SolutionItems) = preProject
+ ..\screenshots\automerge_main.png = ..\screenshots\automerge_main.png
+ ..\screenshots\automerge_teamexplorer.png = ..\screenshots\automerge_teamexplorer.png
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{49184F69-C2BE-4D0C-A9FF-0EEC2C428589}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NuGet", "NuGet", "{96B4F09B-685B-4CF3-9B02-FECE8807BE4C}"
ProjectSection(SolutionItems) = preProject
- ..\build.fsx = ..\build.fsx
+ ..\tools\NuGet\LICENSE.txt = ..\tools\NuGet\LICENSE.txt
+ ..\tools\NuGet\NuGet.exe = ..\tools\NuGet\NuGet.exe
EndProjectSection
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoMerge.Tests", "AutoMerge.Tests\AutoMerge.Tests.csproj", "{4CD4D5BB-FE08-4DAF-A952-93E78022FC12}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoMerge.Standalone", "AutoMerge.Standalone\AutoMerge.Standalone.csproj", "{8B9A3C2D-5F6E-4A1B-9C3D-2E4F5A6B7C8D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -22,12 +95,25 @@ Global
{726ED85E-2274-4D95-B822-B2CFE2CE44B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{726ED85E-2274-4D95-B822-B2CFE2CE44B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{726ED85E-2274-4D95-B822-B2CFE2CE44B9}.Release|Any CPU.Build.0 = Release|Any CPU
- {4CD4D5BB-FE08-4DAF-A952-93E78022FC12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {4CD4D5BB-FE08-4DAF-A952-93E78022FC12}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8B9A3C2D-5F6E-4A1B-9C3D-2E4F5A6B7C8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8B9A3C2D-5F6E-4A1B-9C3D-2E4F5A6B7C8D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8B9A3C2D-5F6E-4A1B-9C3D-2E4F5A6B7C8D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8B9A3C2D-5F6E-4A1B-9C3D-2E4F5A6B7C8D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {8FE189FF-6AED-444C-B5DE-9F841281B0F9}
+ {6C80EF52-0D76-4F42-A66C-B18B1477A8CE} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
+ {067032CB-986B-4AD8-A3E1-5AE11C544A47} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
+ {5DC7FDC7-5BF6-4C05-A817-72C9C8546090} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
+ {2286A832-B2F8-45AE-933A-0A855E5AD542} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
+ {D5AD1EB1-1B80-450D-92E2-C6FECB556576} = {8FE189FF-6AED-444C-B5DE-9F841281B0F9}
+ {A2F06608-443F-4923-8E3B-3BC7E7E40A53} = {8FE189FF-6AED-444C-B5DE-9F841281B0F9}
+ {49184F69-C2BE-4D0C-A9FF-0EEC2C428589} = {8FE189FF-6AED-444C-B5DE-9F841281B0F9}
+ {96B4F09B-685B-4CF3-9B02-FECE8807BE4C} = {49184F69-C2BE-4D0C-A9FF-0EEC2C428589}
+ EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D74AF8A3-6127-40F7-B6C1-E948F866D814}
EndGlobalSection
diff --git a/src/AutoMerge/AutoMerge.csproj b/src/AutoMerge/AutoMerge.csproj
index a8d6876..377c502 100644
--- a/src/AutoMerge/AutoMerge.csproj
+++ b/src/AutoMerge/AutoMerge.csproj
@@ -1,6 +1,12 @@
-
+
+
+ true
+ True
+ True
+ True
+ $(OutDir)
$(VisualStudioVersion)
15.0
Program
@@ -60,33 +66,54 @@
..\..\lib\$(VisualStudioVersion)\Microsoft.TeamFoundation.Client.dll
- False
+ True
..\..\lib\$(VisualStudioVersion)\Microsoft.TeamFoundation.Common.dll
- False
+ True
..\..\lib\$(VisualStudioVersion)\Microsoft.TeamFoundation.Controls.dll
- False
+ True
..\..\lib\$(VisualStudioVersion)\Microsoft.TeamFoundation.VersionControl.Client.dll
- False
+ True
..\..\lib\$(VisualStudioVersion)\Microsoft.TeamFoundation.VersionControl.Common.dll
- False
+ True
..\..\lib\$(VisualStudioVersion)\Microsoft.TeamFoundation.WorkItemTracking.Client.dll
- False
+ True
+
+
+ ..\..\lib\$(VisualStudioVersion)\Microsoft.VisualStudio.Services.Common.dll
+ True
+
+
+ ..\..\lib\$(VisualStudioVersion)\Microsoft.VisualStudio.Services.WebApi.dll
+ True
+
+
+ ..\..\lib\$(VisualStudioVersion)\Newtonsoft.Json.dll
+ True
+
+
+
-
+
+
+
+
+
+
+
@@ -187,7 +214,7 @@
- ResXFileCodeGenerator
+ PublicResXFileCodeGenerator
Resources.Designer.cs
Designer
@@ -220,6 +247,10 @@
true
+
+
+
+
@@ -249,7 +280,6 @@
true
-
diff --git a/src/AutoMerge/AutoMergeNavigationItem.cs b/src/AutoMerge/AutoMergeNavigationItem.cs
index 590daae..fe887f8 100644
--- a/src/AutoMerge/AutoMergeNavigationItem.cs
+++ b/src/AutoMerge/AutoMergeNavigationItem.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.ComponentModel.Composition;
using AutoMerge.Base;
using AutoMerge.VersionControl;
@@ -7,18 +7,18 @@
namespace AutoMerge
{
- [TeamExplorerNavigationItem(GuidList.AutoMergeNavigationItemId, 210, TargetPageId = GuidList.AutoMergePageId)]
- public class AutoMergeNavigationItem : TeamExplorerNavigationItemBase
- {
+ [TeamExplorerNavigationItem(GuidList.AutoMergeNavigationItemId, 210, TargetPageId = GuidList.AutoMergePageId)]
+ public class AutoMergeNavigationItem : TeamExplorerNavigationItemBase
+ {
- [ImportingConstructor]
- public AutoMergeNavigationItem(
- [Import(typeof(SVsServiceProvider))]
- IServiceProvider serviceProvider)
- : base(serviceProvider, GuidList.AutoMergePageId, VersionControlProvider.TeamFoundation)
- {
- Text = Resources.AutoMergePageName;
- Image = Resources.MergeImage;
- }
- }
+ [ImportingConstructor]
+ public AutoMergeNavigationItem(
+ [Import(typeof(SVsServiceProvider))]
+ IServiceProvider serviceProvider)
+ : base(serviceProvider, GuidList.AutoMergePageId, VersionControlProvider.TeamFoundation)
+ {
+ Text = Resources.AutoMergePageName;
+ Image = Resources.MergeImage;
+ }
+ }
}
diff --git a/src/AutoMerge/Base/TeamExplorerSectionViewModelBase.cs b/src/AutoMerge/Base/TeamExplorerSectionViewModelBase.cs
index 5bfb91e..eb526a9 100644
--- a/src/AutoMerge/Base/TeamExplorerSectionViewModelBase.cs
+++ b/src/AutoMerge/Base/TeamExplorerSectionViewModelBase.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Threading.Tasks;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Common.Internal;
@@ -8,96 +8,96 @@
namespace AutoMerge.Base
{
- public abstract class TeamExplorerSectionViewModelBase : TfsTeamExplorerSectionViewModelBase
- {
- private readonly ILogger _logger;
- private static readonly Task _emptyTask = Task.FromResult(0);
+ public abstract class TeamExplorerSectionViewModelBase : TfsTeamExplorerSectionViewModelBase
+ {
+ private readonly ILogger _logger;
+ private static readonly Task _emptyTask = Task.FromResult(0);
- private ITeamFoundationContextManager TfsContextManager { get; set; }
- protected ITeamFoundationContext Context { get; private set; }
+ private ITeamFoundationContextManager TfsContextManager { get; set; }
+ protected ITeamFoundationContext Context { get; private set; }
- protected TeamExplorerSectionViewModelBase(ILogger logger)
- {
- _logger = logger;
- }
+ protected TeamExplorerSectionViewModelBase(ILogger logger)
+ {
+ _logger = logger;
+ }
- protected ILogger Logger { get { return _logger; } }
+ protected ILogger Logger { get { return _logger; } }
- protected virtual Task RefreshAsync()
- {
- return _emptyTask;
- }
+ protected virtual Task RefreshAsync()
+ {
+ return _emptyTask;
+ }
- protected virtual Task InitializeAsync(object sender, SectionInitializeEventArgs e)
- {
- return _emptyTask;
- }
+ protected virtual Task InitializeAsync(object sender, SectionInitializeEventArgs e)
+ {
+ return _emptyTask;
+ }
- public async override void Initialize(object sender, SectionInitializeEventArgs e)
- {
- ShowBusy();
-
- try
- {
- base.Initialize(sender, e);
- if (ServiceProvider != null)
- {
- TfsContextManager = ServiceProvider.GetService();
- if (TfsContextManager != null)
- {
- TfsContextManager.ContextChanged -= OnContextChanged;
- TfsContextManager.ContextChanged += OnContextChanged;
- var context = TfsContextManager.CurrentContext;
- Context = context;
- }
- }
- await InitializeAsync(sender, e);
- }
- catch (Exception ex)
- {
- ShowError(ex.Message);
- }
-
- HideBusy();
- }
+ public async override void Initialize(object sender, SectionInitializeEventArgs e)
+ {
+ ShowBusy();
- public async override void Refresh()
+ try
+ {
+ base.Initialize(sender, e);
+ if (ServiceProvider != null)
{
- ShowBusy();
-
- try
- {
- await RefreshAsync();
- }
- catch (Exception ex)
- {
- ShowError(ex.Message);
- _logger.Error(ex.Message, ex);
- }
-
- HideBusy();
+ TfsContextManager = ServiceProvider.GetService();
+ if (TfsContextManager != null)
+ {
+ TfsContextManager.ContextChanged -= OnContextChanged;
+ TfsContextManager.ContextChanged += OnContextChanged;
+ var context = TfsContextManager.CurrentContext;
+ Context = context;
+ }
}
+ await InitializeAsync(sender, e);
+ }
+ catch (Exception ex)
+ {
+ ShowError(ex.Message);
+ }
+
+ HideBusy();
+ }
- protected void SetMvvmFocus(string id, params object[] args)
- {
- var focusService = TryResolveService();
- if (focusService == null)
- return;
- focusService.SetFocus(id, args);
- }
+ public async override void Refresh()
+ {
+ ShowBusy();
+
+ try
+ {
+ await RefreshAsync();
+ }
+ catch (Exception ex)
+ {
+ ShowError(ex.Message);
+ _logger.Error(ex.Message, ex);
+ }
+
+ HideBusy();
+ }
- public override void Dispose()
- {
- base.Dispose();
- if (TfsContextManager != null)
- {
- TfsContextManager.ContextChanged -= OnContextChanged;
- }
- }
+ protected void SetMvvmFocus(string id, params object[] args)
+ {
+ var focusService = TryResolveService();
+ if (focusService == null)
+ return;
+ focusService.SetFocus(id, args);
+ }
- protected virtual void OnContextChanged(object sender, ContextChangedEventArgs e)
- {
+ public override void Dispose()
+ {
+ base.Dispose();
+ if (TfsContextManager != null)
+ {
+ TfsContextManager.ContextChanged -= OnContextChanged;
+ }
+ }
+
+ protected virtual void OnContextChanged(object sender, ContextChangedEventArgs e)
+ {
- }
}
+ }
}
diff --git a/src/AutoMerge/Branches/BranchesViewModel.cs b/src/AutoMerge/Branches/BranchesViewModel.cs
index ec7d9e8..e9949c4 100644
--- a/src/AutoMerge/Branches/BranchesViewModel.cs
+++ b/src/AutoMerge/Branches/BranchesViewModel.cs
@@ -21,1361 +21,1414 @@
namespace AutoMerge
{
- public sealed class BranchesViewModel : TeamExplorerSectionViewModelBase
- {
- private readonly IEventAggregator _eventAggregator;
- private ChangesetService _changesetService;
- private Workspace _workspace;
+ public sealed class BranchesViewModel : TeamExplorerSectionViewModelBase
+ {
+ private readonly IEventAggregator _eventAggregator;
+ private ChangesetService _changesetService;
+ private Workspace _workspace;
- private ChangesetViewModel _changeset;
- private bool _merging;
+ private ChangesetViewModel _changeset;
+ private bool _merging;
- public BranchesViewModel(ILogger logger)
- : base(logger)
- {
- Title = Resources.BrancheSectionName;
- IsVisible = true;
- IsExpanded = true;
- IsBusy = false;
+ public BranchesViewModel(ILogger logger)
+ : base(logger)
+ {
+ Title = Resources.BrancheSectionName;
+ IsVisible = true;
+ IsExpanded = true;
+ IsBusy = false;
- MergeCommand = new DelegateCommand(MergeExecute, m => MergeCanEcexute());
- SelectWorkspaceCommand = new DelegateCommand(SelectWorkspaceExecute);
- OpenSourceControlExplorerCommand = new DelegateCommand(OpenSourceControlExplorerExecute, OpenSourceControlExplorerCanExecute);
+ MergeCommand = new DelegateCommand(MergeExecute, m => MergeCanEcexute());
+ SelectWorkspaceCommand = new DelegateCommand(SelectWorkspaceExecute);
+ OpenSourceControlExplorerCommand = new DelegateCommand(OpenSourceControlExplorerExecute, OpenSourceControlExplorerCanExecute);
- _eventAggregator = EventAggregatorFactory.Get();
- _merging = false;
- }
+ _eventAggregator = EventAggregatorFactory.Get();
+ _merging = false;
+ }
- public ObservableCollection Branches
- {
- get
- {
- return _branches;
- }
- set
- {
- _branches = value;
- RaisePropertyChanged("Branches");
- }
- }
- private ObservableCollection _branches;
+ public ObservableCollection Branches
+ {
+ get
+ {
+ return _branches;
+ }
+ set
+ {
+ _branches = value;
+ RaisePropertyChanged("Branches");
+ }
+ }
+ private ObservableCollection _branches;
- private MergeInfoViewModel _selectedBranch;
+ private MergeInfoViewModel _selectedBranch;
- public MergeInfoViewModel SelectedBranch
- {
- get
- {
- return _selectedBranch;
- }
- set
- {
- _selectedBranch = value;
- RaisePropertyChanged("SelectedBranch");
- }
- }
+ public MergeInfoViewModel SelectedBranch
+ {
+ get
+ {
+ return _selectedBranch;
+ }
+ set
+ {
+ _selectedBranch = value;
+ RaisePropertyChanged("SelectedBranch");
+ }
+ }
- public DelegateCommand MergeCommand { get; private set; }
+ public DelegateCommand MergeCommand { get; private set; }
- public MergeOption MergeOption
- {
- get { return _mergeOption; }
- set
- {
- _mergeOption = value;
- RaisePropertyChanged("MergeOption");
- }
- }
- private MergeOption _mergeOption;
+ public MergeOption MergeOption
+ {
+ get { return _mergeOption; }
+ set
+ {
+ _mergeOption = value;
+ RaisePropertyChanged("MergeOption");
+ }
+ }
+ private MergeOption _mergeOption;
- public string ErrorMessage
- {
- get
- {
- return _errorMessage;
- }
- set
- {
- _errorMessage = value;
- RaisePropertyChanged("ErrorMessage");
- }
- }
- private string _errorMessage;
+ public string ErrorMessage
+ {
+ get
+ {
+ return _errorMessage;
+ }
+ set
+ {
+ _errorMessage = value;
+ RaisePropertyChanged("ErrorMessage");
+ }
+ }
+ private string _errorMessage;
- public Workspace Workspace
- {
- get
- {
- return _workspace;
- }
- set
- {
- _workspace = value;
- RaisePropertyChanged("Workspace");
- }
- }
+ public Workspace Workspace
+ {
+ get
+ {
+ return _workspace;
+ }
+ set
+ {
+ _workspace = value;
+ RaisePropertyChanged("Workspace");
+ }
+ }
- private ObservableCollection _workspaces;
+ private ObservableCollection _workspaces;
- public ObservableCollection Workspaces
- {
- get
- {
- return _workspaces;
- }
- set
- {
- _workspaces = value;
- RaisePropertyChanged("Workspaces");
- }
- }
+ public ObservableCollection Workspaces
+ {
+ get
+ {
+ return _workspaces;
+ }
+ set
+ {
+ _workspaces = value;
+ RaisePropertyChanged("Workspaces");
+ }
+ }
- private bool _showWorkspaceChooser;
- public bool ShowWorkspaceChooser
- {
- get
- {
- return _showWorkspaceChooser;
- }
- set
- {
- _showWorkspaceChooser = value;
- RaisePropertyChanged("ShowWorkspaceChooser");
- }
- }
+ private bool _showWorkspaceChooser;
+ public bool ShowWorkspaceChooser
+ {
+ get
+ {
+ return _showWorkspaceChooser;
+ }
+ set
+ {
+ _showWorkspaceChooser = value;
+ RaisePropertyChanged("ShowWorkspaceChooser");
+ }
+ }
- private MergeMode _mergeMode;
- public MergeMode MergeMode
- {
- get
- {
- return _mergeMode;
- }
- set
- {
- _mergeMode = value;
- RaisePropertyChanged("MergeMode");
- }
- }
+ private MergeMode _mergeMode;
+ public MergeMode MergeMode
+ {
+ get
+ {
+ return _mergeMode;
+ }
+ set
+ {
+ _mergeMode = value;
+ RaisePropertyChanged("MergeMode");
+ }
+ }
- private ObservableCollection _mergeModes;
+ private ObservableCollection _mergeModes;
- public ObservableCollection MergeModes
- {
- get
- {
- return _mergeModes;
- }
- set
- {
- _mergeModes = value;
- RaisePropertyChanged("MergeModes");
- }
- }
+ public ObservableCollection MergeModes
+ {
+ get
+ {
+ return _mergeModes;
+ }
+ set
+ {
+ _mergeModes = value;
+ RaisePropertyChanged("MergeModes");
+ }
+ }
- public DelegateCommand SelectWorkspaceCommand { get; set; }
+ public DelegateCommand SelectWorkspaceCommand { get; set; }
- public DelegateCommand OpenSourceControlExplorerCommand { get; set; }
+ public DelegateCommand OpenSourceControlExplorerCommand { get; set; }
- private static ObservableCollection GetWorkspaces(VersionControlServer versionControl, TfsTeamProjectCollection tfs)
- {
- var queryWorkspaces = versionControl.QueryWorkspaces(null, tfs.AuthorizedIdentity.UniqueName, Environment.MachineName);
- if (queryWorkspaces.Length > 1)
- {
- return new ObservableCollection(queryWorkspaces.OrderBy(w => w.Name));
- }
- return new ObservableCollection(queryWorkspaces);
- }
+ private static ObservableCollection GetWorkspaces(VersionControlServer versionControl, TfsTeamProjectCollection tfs)
+ {
+ var queryWorkspaces = versionControl.QueryWorkspaces(null, tfs.AuthorizedIdentity.UniqueName, Environment.MachineName);
+ if (queryWorkspaces.Length > 1)
+ {
+ return new ObservableCollection(queryWorkspaces.OrderBy(w => w.Name));
+ }
+ return new ObservableCollection(queryWorkspaces);
+ }
- protected async override Task InitializeAsync(object sender, SectionInitializeEventArgs e)
- {
- Logger.Debug("Start initilize branches section");
+ protected async override Task InitializeAsync(object sender, SectionInitializeEventArgs e)
+ {
+ Logger.Debug("Start initialize branches section");
- var tfs = Context.TeamProjectCollection;
- var versionControl = tfs.GetService();
- SubscribeWorkspaceChanges(versionControl);
+ // Wait for context to be available if navigating from toolbar/menu
+ TfsTeamProjectCollection tfs = null;
+ VersionControlServer versionControl = null;
- _changesetService = new ChangesetService(versionControl);
+ if (Context?.TeamProjectCollection == null)
+ {
+ Logger.Debug("Context.TeamProjectCollection is null, attempting to get context from ServiceProvider...");
- _eventAggregator.GetEvent()
- .Subscribe(OnSelectedChangeset);
- _eventAggregator.GetEvent()
- .Subscribe(OnBranchSelectedChanged);
+ // Try to get context directly from ServiceProvider
+ var maxRetries = 20;
+ var retryCount = 0;
+ while (retryCount < maxRetries)
+ {
+ if (Context?.TeamProjectCollection != null)
+ {
+ tfs = Context.TeamProjectCollection;
+ break;
+ }
+
+ // Also try getting it through VersionControlNavigationHelper
+ var contextFromHelper = VersionControlNavigationHelper.GetTeamFoundationContext(ServiceProvider);
+ if (contextFromHelper?.TeamProjectCollection != null)
+ {
+ tfs = contextFromHelper.TeamProjectCollection;
+ Logger.Debug("Got TeamProjectCollection from VersionControlNavigationHelper");
+ break;
+ }
+
+ await Task.Delay(100);
+ retryCount++;
+ }
- if (e.Context == null)
- {
- Workspaces = GetWorkspaces(versionControl, tfs);
- if (Workspaces.Count > 0)
- {
- Workspace = WorkspaceHelper.GetWorkspace(versionControl, Workspaces);
- ShowWorkspaceChooser = Workspaces.Count > 1;
- }
- else
- {
- Workspace = null;
- }
+ if (tfs == null)
+ {
+ Logger.Error("TeamProjectCollection is still null after waiting");
+ ErrorMessage = "Unable to connect to Team Project. Please ensure you are connected to a TFS/Azure DevOps project.";
+ Branches = new ObservableCollection();
+ return;
+ }
+ }
+ else
+ {
+ tfs = Context.TeamProjectCollection;
+ }
+
+ versionControl = tfs.GetService();
+ SubscribeWorkspaceChanges(versionControl);
+
+ _changesetService = new ChangesetService(versionControl);
+
+ _eventAggregator.GetEvent()
+ .Subscribe(OnSelectedChangeset);
+ _eventAggregator.GetEvent()
+ .Subscribe(OnBranchSelectedChanged);
+
+ if (e.Context == null)
+ {
+ Workspaces = GetWorkspaces(versionControl, tfs);
+ if (Workspaces.Count > 0)
+ {
+ Workspace = WorkspaceHelper.GetWorkspace(versionControl, Workspaces);
+ ShowWorkspaceChooser = Workspaces.Count > 1;
+ }
+ else
+ {
+ Workspace = null;
+ }
- MergeModes = new ObservableCollection
+ MergeModes = new ObservableCollection
{
MergeMode.Merge,
MergeMode.MergeAndCheckIn
};
- MergeMode = Settings.Instance.LastMergeOperation;
+ MergeMode = Settings.Instance.LastMergeOperation;
- await RefreshAsync();
- }
- else
- {
- RestoreContext(e);
- }
+ await RefreshAsync();
+ }
+ else
+ {
+ RestoreContext(e);
+ }
- Logger.Debug("End initialize branches section");
- }
+ Logger.Debug("End initialize branches section");
+ }
- private void OnBranchSelectedChanged(MergeInfoViewModel obj)
- {
- MergeCommand.RaiseCanExecuteChanged();
- }
+ private void OnBranchSelectedChanged(MergeInfoViewModel obj)
+ {
+ MergeCommand.RaiseCanExecuteChanged();
+ }
- ///
- /// Refresh the changeset data asynchronously.
- ///
- protected override async Task RefreshAsync()
+ ///
+ /// Refresh the changeset data asynchronously.
+ ///
+ protected override async Task RefreshAsync()
+ {
+ var changeset = _changeset;
+ Logger.Debug("Start refresh branches section for changeset {0} ...",
+ changeset == null ? "null" : changeset.ChangesetId.ToString(CultureInfo.InvariantCulture));
+
+ string errorMessage = null;
+ if (Workspaces.Count == 0)
+ {
+ errorMessage = "Workspaces not found";
+ }
+ errorMessage = errorMessage ?? CalculateError(changeset);
+ if (changeset == null || !string.IsNullOrEmpty(errorMessage))
+ {
+ ErrorMessage = errorMessage;
+ Branches = new ObservableCollection();
+ }
+ else
+ {
+ Logger.Info("Getting branches for changeset {0} ...",
+ changeset.ChangesetId.ToString(CultureInfo.InvariantCulture));
+ if (Context?.TeamProjectCollection == null)
{
- var changeset = _changeset;
- Logger.Debug("Start refresh branches section for changeset {0} ...",
- changeset == null ? "null" : changeset.ChangesetId.ToString(CultureInfo.InvariantCulture));
-
- string errorMessage = null;
- if (Workspaces.Count == 0)
- {
- errorMessage = "Workspaces not found";
- }
- errorMessage = errorMessage ?? CalculateError(changeset);
- if (changeset == null || !string.IsNullOrEmpty(errorMessage))
- {
- ErrorMessage = errorMessage;
- Branches = new ObservableCollection();
- }
- else
- {
- Logger.Info("Getting branches for changeset {0} ...",
- changeset.ChangesetId.ToString(CultureInfo.InvariantCulture));
- var branches = await Task.Run(() => GetBranches(Context, changeset));
- Logger.Info("Getting branches end for changeset {0}",
- changeset.ChangesetId.ToString(CultureInfo.InvariantCulture));
-
- // Selected changeset in sequence
- if (changeset.ChangesetId == _changeset.ChangesetId)
- {
- Branches = branches;
- ErrorMessage = branches.Count <= 1 ? "Target branches not found" : null;
- MergeCommand.RaiseCanExecuteChanged();
- }
- }
- Logger.Debug("End refresh branches section for changeset {0}",
- changeset == null ? "null" : changeset.ChangesetId.ToString(CultureInfo.InvariantCulture));
+ Logger.Error("Unable to load branches: TeamProjectCollection context is not available.");
+ ErrorMessage = "Unable to connect to Team Project. Please ensure you are connected to a TFS/Azure DevOps project.";
+ Branches = new ObservableCollection();
+ return;
}
- private static string CalculateError(ChangesetViewModel changeset)
- {
- if (changeset == null)
- return "Changeset not selected";
-
- if (changeset.Branches.IsNullOrEmpty())
- return "Changeset has not branch";
-
- if (changeset.Branches.Count > 1)
- return string.Format("Changeset has {0} branches. Merge not possible.", changeset.Branches.Count);
+ var branches = await Task.Run(() => GetBranches(Context.TeamProjectCollection, changeset, _workspace, _changesetService, _eventAggregator));
+ Logger.Info("Getting branches end for changeset {0}",
+ changeset.ChangesetId.ToString(CultureInfo.InvariantCulture));
- return null;
- }
-
- private void OnSelectedChangeset(ChangesetViewModel changeset)
+ // Selected changeset in sequence
+ if (changeset.ChangesetId == _changeset.ChangesetId)
{
- _changeset = changeset;
- Refresh();
+ Branches = branches;
+ ErrorMessage = branches.Count <= 1 ? "Target branches not found" : null;
+ MergeCommand.RaiseCanExecuteChanged();
}
+ }
+ Logger.Debug("End refresh branches section for changeset {0}",
+ changeset == null ? "null" : changeset.ChangesetId.ToString(CultureInfo.InvariantCulture));
+ }
- private ObservableCollection GetBranches(ITeamFoundationContext context, ChangesetViewModel changesetViewModel)
- {
- if (context == null)
- return new ObservableCollection();
- var tfs = context.TeamProjectCollection;
- var versionControl = tfs.GetService();
+ private static string CalculateError(ChangesetViewModel changeset)
+ {
+ if (changeset == null)
+ return "Changeset not selected";
- var result = new ObservableCollection();
+ if (changeset.Branches.IsNullOrEmpty())
+ return "Changeset has no branch";
- var workspace = _workspace;
+ if (changeset.Branches.Count > 1)
+ return string.Format("Changeset has {0} branches. Merge not possible.", changeset.Branches.Count);
- var changesetService = _changesetService;
+ return null;
+ }
- var changes = changesetService.GetChanges(changesetViewModel.ChangesetId);
+ private void OnSelectedChangeset(ChangesetViewModel changeset)
+ {
+ _changeset = changeset;
+ Refresh();
+ }
- var sourceTopFolder = CalculateTopFolder(changes);
- var mergesRelationships = GetMergesRelationships(sourceTopFolder, versionControl);
+ public static ObservableCollection GetBranches(
+ TfsTeamProjectCollection tfs,
+ ChangesetViewModel changesetViewModel,
+ Workspace workspace,
+ ChangesetService changesetService,
+ IEventAggregator eventAggregator)
+ {
+ if (tfs == null || changesetViewModel == null || changesetService == null || workspace == null || eventAggregator == null)
+ return new ObservableCollection();
- if (mergesRelationships.Count > 0)
- {
- var sourceBranchIdentifier = changesetViewModel.Branches.Select(b => new ItemIdentifier(b)).First();
+ var versionControl = tfs.GetService();
- var sourceBranch = sourceBranchIdentifier.Item;
+ var result = new ObservableCollection();
- var trackMerges = versionControl.TrackMerges(new[] { changesetViewModel.ChangesetId },
- new ItemIdentifier(sourceTopFolder),
- mergesRelationships.ToArray(),
- null);
+ var changes = changesetService.GetChanges(changesetViewModel.ChangesetId);
- var changesetVersionSpec = new ChangesetVersionSpec(changesetViewModel.ChangesetId);
+ var sourceTopFolder = CalculateTopFolder(changes);
+ var mergesRelationships = GetMergesRelationships(sourceTopFolder, versionControl);
- var branchValidator = new BranchValidator(workspace, trackMerges);
- var branchFactory = new BranchFactory(sourceBranch, sourceTopFolder,
- changesetVersionSpec, branchValidator,
- _eventAggregator);
+ if (mergesRelationships.Count > 0)
+ {
+ var sourceBranchIdentifier = changesetViewModel.Branches.Select(b => new ItemIdentifier(b)).First();
- var sourceBranchInfo = versionControl.QueryBranchObjects(sourceBranchIdentifier, RecursionType.None)[0];
- if (sourceBranchInfo.Properties != null && sourceBranchInfo.Properties.ParentBranch != null
- && !sourceBranchInfo.Properties.ParentBranch.IsDeleted)
- {
- var targetBranch = sourceBranchInfo.Properties.ParentBranch;
- var targetPath = GetTargetPath(mergesRelationships, targetBranch);
- if (targetPath != null)
- {
- var mergeInfo = branchFactory.CreateTargetBranchInfo(targetBranch, targetPath);
- mergeInfo._checked = mergeInfo.ValidationResult == BranchValidationResult.Success;
+ var sourceBranch = sourceBranchIdentifier.Item;
- result.Add(mergeInfo);
- }
- }
+ var trackMerges = versionControl.TrackMerges(new[] { changesetViewModel.ChangesetId },
+ new ItemIdentifier(sourceTopFolder),
+ mergesRelationships.ToArray(),
+ null);
- var currentBranchInfo = branchFactory.CreateSourceBranch();
- result.Add(currentBranchInfo);
+ var changesetVersionSpec = new ChangesetVersionSpec(changesetViewModel.ChangesetId);
- if (sourceBranchInfo.ChildBranches != null)
- {
- var childBranches = sourceBranchInfo.ChildBranches.Where(b => !b.IsDeleted)
- .Reverse();
- foreach (var childBranch in childBranches)
- {
- var targetBranch = childBranch;
- var targetPath = GetTargetPath(mergesRelationships, targetBranch);
- if (targetPath != null)
- {
- var mergeInfo = branchFactory.CreateTargetBranchInfo(targetBranch, targetPath);
- result.Add(mergeInfo);
- }
- }
- }
-
- // Feature branch
- if (mergesRelationships.Count > 0)
- {
- var changetIds =
- mergesRelationships.Select(r => r.Version).Cast().Select(c => c.ChangesetId)
- .Distinct()
- .ToArray();
- var branches = _changesetService.GetAssociatedBranches(changetIds);
-
- foreach (var mergesRelationship in mergesRelationships)
- {
- var targetBranch = branches.FirstOrDefault(b => IsTargetPath(mergesRelationship, b));
- if (targetBranch != null)
- {
- var mergeInfo = branchFactory.CreateTargetBranchInfo(targetBranch, mergesRelationship);
- result.Add(mergeInfo);
- }
- }
- }
- }
-
- return result;
- }
+ var branchValidator = new BranchValidator(workspace, trackMerges);
+ var branchFactory = new BranchFactory(sourceBranch, sourceTopFolder,
+ changesetVersionSpec, branchValidator,
+ eventAggregator);
- private static List GetMergesRelationships(string sourceTopFolder, VersionControlServer versionControl)
+ var sourceBranchInfo = versionControl.QueryBranchObjects(sourceBranchIdentifier, RecursionType.None)[0];
+ if (sourceBranchInfo.Properties != null && sourceBranchInfo.Properties.ParentBranch != null
+ && !sourceBranchInfo.Properties.ParentBranch.IsDeleted)
{
- return versionControl.QueryMergeRelationships(sourceTopFolder)
- .Where(r => !r.IsDeleted)
- .ToList();
+ var targetBranch = sourceBranchInfo.Properties.ParentBranch;
+ var targetPath = GetTargetPath(mergesRelationships, targetBranch);
+ if (targetPath != null)
+ {
+ var mergeInfo = branchFactory.CreateTargetBranchInfo(targetBranch, targetPath);
+ mergeInfo._checked = mergeInfo.ValidationResult == BranchValidationResult.Success;
+
+ result.Add(mergeInfo);
+ }
}
- private TrackMergeInfo GetTrackMergeInfo(VersionControlServer versionControl,
- IEnumerable allTrackMerges,
- string sourcePath)
- {
- var result = new TrackMergeInfo
- {
- FromOriginalToSourceBranches = new List(),
- };
-
- // INTACT Tweak based on ihcaesar:branch_not_found PR
- var trackMerges = allTrackMerges.Where(m => string.Equals(m.TargetItem.Item, sourcePath, StringComparison.OrdinalIgnoreCase)).ToArray();
- //var trackMerges = allTrackMerges.Where(m => m.TargetItem.Item == sourcePath).ToArray();
+ var currentBranchInfo = branchFactory.CreateSourceBranch();
+ result.Add(currentBranchInfo);
- if (!trackMerges.IsNullOrEmpty())
- {
- var changesetIds = trackMerges.Select(t => t.SourceChangeset.ChangesetId).ToArray();
- var mergeSourceBranches = _changesetService.GetAssociatedBranches(changesetIds)
- .Select(b => b.Item)
- .Distinct()
- .ToArray();
-
- if (mergeSourceBranches.Length == 1)
- {
- result.FromOriginalToSourceBranches.Add(mergeSourceBranches[0]);
-
- var sourceFolder = trackMerges.First().SourceItem.Item.ServerItem;
- var comment = trackMerges.First().SourceChangeset.Comment;
- if (trackMerges.Length > 1)
- {
- foreach (var merge in trackMerges.Skip(1))
- sourceFolder = FindShareFolder(sourceFolder, merge.SourceItem.Item.ServerItem);
- comment = "source changeset has several comments";
- }
-
- var sourceMergesRelationships = versionControl.QueryMergeRelationships(sourceFolder)
- .Where(r => !r.IsDeleted)
- .ToArray();
-
- var sourceTrackMerges = versionControl.TrackMerges(changesetIds,
- new ItemIdentifier(sourceFolder),
- sourceMergesRelationships,
- null);
-
- var sourceTrackMergeInfo = GetTrackMergeInfo(versionControl, sourceTrackMerges, sourceFolder);
-
- if (!sourceTrackMergeInfo.FromOriginalToSourceBranches.IsNullOrEmpty())
- {
- result.FromOriginalToSourceBranches.AddRange(sourceTrackMergeInfo.FromOriginalToSourceBranches);
- result.OriginalComment = sourceTrackMergeInfo.OriginalComment;
- result.OriginaBranch = sourceTrackMergeInfo.OriginaBranch;
- }
- else
- {
- result.OriginalComment = comment;
- result.OriginaBranch = mergeSourceBranches[0];
- }
- }
- else
- {
- result.FromOriginalToSourceBranches.Add("multi");
- result.OriginaBranch = "multi";
- result.OriginalComment = "source changeset has several comments";
- }
+ if (sourceBranchInfo.ChildBranches != null)
+ {
+ var childBranches = sourceBranchInfo.ChildBranches.Where(b => !b.IsDeleted)
+ .Reverse();
+ foreach (var childBranch in childBranches)
+ {
+ var targetBranch = childBranch;
+ var targetPath = GetTargetPath(mergesRelationships, targetBranch);
+ if (targetPath != null)
+ {
+ var mergeInfo = branchFactory.CreateTargetBranchInfo(targetBranch, targetPath);
+ result.Add(mergeInfo);
}
-
- return result;
+ }
}
- private static ItemIdentifier GetTargetPath(ICollection mergesRelationships, ItemIdentifier targetBranch)
+ // Feature branch
+ if (mergesRelationships.Count > 0)
{
- if (mergesRelationships == null || mergesRelationships.Count == 0)
- return null;
- var targetItem = mergesRelationships.FirstOrDefault(m => IsTargetPath(m, targetBranch));
- if (targetItem != null)
- {
- mergesRelationships.Remove(targetItem);
- return targetItem;
+ var changetIds =
+ mergesRelationships.Select(r => r.Version).Cast().Select(c => c.ChangesetId)
+ .Distinct()
+ .ToArray();
+ var branches = changesetService.GetAssociatedBranches(changetIds);
+
+ foreach (var mergesRelationship in mergesRelationships)
+ {
+ var targetBranch = branches.FirstOrDefault(b => IsTargetPath(mergesRelationship, b));
+ if (targetBranch != null)
+ {
+ var mergeInfo = branchFactory.CreateTargetBranchInfo(targetBranch, mergesRelationship);
+ result.Add(mergeInfo);
}
-
- return null;
+ }
}
+ }
- private static bool IsTargetPath(ItemIdentifier mergeRelations, ItemIdentifier branch)
- {
- // INTACT Tweak based on ihcaesar:branch_not_found PR
- return mergeRelations.Item.IndexOf(branch.Item + '/', StringComparison.OrdinalIgnoreCase) >= 0 ||
- string.Compare(mergeRelations.Item, branch.Item, StringComparison.OrdinalIgnoreCase) == 0;
+ return result;
+ }
- // INTACT Tweak to improve hit rates
- //return mergeRelations.Item.Contains(branch.Item + "/"); // ORIGINAL
- //return mergeRelations.Item.StartsWith(branch.Item); // INTACT
- }
+ private static List GetMergesRelationships(string sourceTopFolder, VersionControlServer versionControl)
+ {
+ return versionControl.QueryMergeRelationships(sourceTopFolder)
+ .Where(r => !r.IsDeleted)
+ .ToList();
+ }
- private static string CalculateTopFolder(IList changes)
+ private TrackMergeInfo GetTrackMergeInfo(VersionControlServer versionControl,
+ IEnumerable allTrackMerges,
+ string sourcePath)
+ {
+ var result = new TrackMergeInfo
+ {
+ FromOriginalToSourceBranches = new List(),
+ };
+
+ // INTACT Tweak based on ihcaesar:branch_not_found PR
+ var trackMerges = allTrackMerges.Where(m => string.Equals(m.TargetItem.Item, sourcePath, StringComparison.OrdinalIgnoreCase)).ToArray();
+ //var trackMerges = allTrackMerges.Where(m => m.TargetItem.Item == sourcePath).ToArray();
+
+ if (!trackMerges.IsNullOrEmpty())
+ {
+ var changesetIds = trackMerges.Select(t => t.SourceChangeset.ChangesetId).ToArray();
+ var mergeSourceBranches = _changesetService.GetAssociatedBranches(changesetIds)
+ .Select(b => b.Item)
+ .Distinct()
+ .ToArray();
+
+ if (mergeSourceBranches.Length == 1)
{
- if (changes == null || changes.Count == 0)
- throw new ArgumentNullException("changes");
-
- string topFolder = null;
- if (changes.Count == 1 &&
- (changes[0].ChangeType.HasFlag(ChangeType.Edit)
- && !changes[0].ChangeType.HasFlag(ChangeType.Add)
- && !changes[0].ChangeType.HasFlag(ChangeType.Branch)))
- {
- topFolder = changes[0].Item.ServerItem;
- }
- else
- {
- foreach (var change in changes)
- {
-// if (SkipChange(change.ChangeType, change.Item))
-// continue;
-
-// if (topFolder != null)
-// {
-// if (!IsNeedCalculateTopFolder(change.ChangeType, change.Item) change.Item.ServerItem.Contains(topFolder) && change.Item.ServerItem != topFolder)
-// continue;
-// }
-
- var changeFolder = ExtractFolder(change.ChangeType, change.Item);
- if (changeFolder != topFolder)
- topFolder = FindShareFolder(topFolder, changeFolder);
- }
- }
-
- if (topFolder != null && topFolder.EndsWith("/"))
- {
- topFolder = topFolder.Substring(0, topFolder.Length - 1);
- }
-
- return topFolder;
+ result.FromOriginalToSourceBranches.Add(mergeSourceBranches[0]);
+
+ var sourceFolder = trackMerges.First().SourceItem.Item.ServerItem;
+ var comment = trackMerges.First().SourceChangeset.Comment;
+ if (trackMerges.Length > 1)
+ {
+ foreach (var merge in trackMerges.Skip(1))
+ sourceFolder = FindShareFolder(sourceFolder, merge.SourceItem.Item.ServerItem);
+ comment = "source changeset has several comments";
+ }
+
+ var sourceMergesRelationships = versionControl.QueryMergeRelationships(sourceFolder)
+ .Where(r => !r.IsDeleted)
+ .ToArray();
+
+ var sourceTrackMerges = versionControl.TrackMerges(changesetIds,
+ new ItemIdentifier(sourceFolder),
+ sourceMergesRelationships,
+ null);
+
+ var sourceTrackMergeInfo = GetTrackMergeInfo(versionControl, sourceTrackMerges, sourceFolder);
+
+ if (!sourceTrackMergeInfo.FromOriginalToSourceBranches.IsNullOrEmpty())
+ {
+ result.FromOriginalToSourceBranches.AddRange(sourceTrackMergeInfo.FromOriginalToSourceBranches);
+ result.OriginalComment = sourceTrackMergeInfo.OriginalComment;
+ result.OriginaBranch = sourceTrackMergeInfo.OriginaBranch;
+ }
+ else
+ {
+ result.OriginalComment = comment;
+ result.OriginaBranch = mergeSourceBranches[0];
+ }
}
-
- private static string FindShareFolder(string topFolder, string changeFolder)
+ else
{
- // INTACT Tweak based on ihcaesar:branch_not_found PR
- //if ((topFolder == null) || topFolder.Contains(changeFolder))
- if ((topFolder == null) || topFolder.IndexOf(changeFolder, StringComparison.OrdinalIgnoreCase) >= 0)
- {
- return changeFolder;
- }
- const string rootFolder = "$/";
- var folder = topFolder;
- while (folder != rootFolder && !changeFolder.StartsWith(folder, StringComparison.OrdinalIgnoreCase))
- {
- folder = ExtractParentFolder(folder);
- if (folder != null && changeFolder.StartsWith(folder, StringComparison.OrdinalIgnoreCase))
- break;
- }
-
- return folder == rootFolder ? folder + "/" : folder;
+ result.FromOriginalToSourceBranches.Add("multi");
+ result.OriginaBranch = "multi";
+ result.OriginalComment = "source changeset has several comments";
}
+ }
+
+ return result;
+ }
+
+ private static ItemIdentifier GetTargetPath(ICollection mergesRelationships, ItemIdentifier targetBranch)
+ {
+ if (mergesRelationships == null || mergesRelationships.Count == 0)
+ return null;
+ var targetItem = mergesRelationships.FirstOrDefault(m => IsTargetPath(m, targetBranch));
+ if (targetItem != null)
+ {
+ mergesRelationships.Remove(targetItem);
+ return targetItem;
+ }
+
+ return null;
+ }
-// private static bool SkipChange(ChangeType changeType, Item item)
-// {
-// return changeType.HasFlag(ChangeType.SourceRename) && changeType.HasFlag(ChangeType.Delete);
-// }
+ private static bool IsTargetPath(ItemIdentifier mergeRelations, ItemIdentifier branch)
+ {
+ // INTACT Tweak based on ihcaesar:branch_not_found PR
+ return mergeRelations.Item.IndexOf(branch.Item + '/', StringComparison.OrdinalIgnoreCase) >= 0 ||
+ string.Compare(mergeRelations.Item, branch.Item, StringComparison.OrdinalIgnoreCase) == 0;
- private static string ExtractFolder(ChangeType changeType, Item item)
+ // INTACT Tweak to improve hit rates
+ //return mergeRelations.Item.Contains(branch.Item + "/"); // ORIGINAL
+ //return mergeRelations.Item.StartsWith(branch.Item); // INTACT
+ }
+
+ private static string CalculateTopFolder(IList changes)
+ {
+ if (changes == null || changes.Count == 0)
+ throw new ArgumentNullException("changes");
+
+ string topFolder = null;
+ if (changes.Count == 1 &&
+ (changes[0].ChangeType.HasFlag(ChangeType.Edit)
+ && !changes[0].ChangeType.HasFlag(ChangeType.Add)
+ && !changes[0].ChangeType.HasFlag(ChangeType.Branch)))
+ {
+ topFolder = changes[0].Item.ServerItem;
+ }
+ else
+ {
+ foreach (var change in changes)
{
- return ExtractFolder(changeType, item.ServerItem, item.ItemType);
+ // if (SkipChange(change.ChangeType, change.Item))
+ // continue;
+
+ // if (topFolder != null)
+ // {
+ // if (!IsNeedCalculateTopFolder(change.ChangeType, change.Item) change.Item.ServerItem.Contains(topFolder) && change.Item.ServerItem != topFolder)
+ // continue;
+ // }
+
+ var changeFolder = ExtractFolder(change.ChangeType, change.Item);
+ if (changeFolder != topFolder)
+ topFolder = FindShareFolder(topFolder, changeFolder);
}
+ }
- private static string ExtractFolder(ChangeType changeType, string path, ItemType itemType)
- {
- if (IsNeedCalculateTopFolder(changeType, itemType))
- return ExtractParentFolder(path);
+ if (topFolder != null && topFolder.EndsWith("/"))
+ {
+ topFolder = topFolder.Substring(0, topFolder.Length - 1);
+ }
- return itemType == ItemType.Folder
- ? path
- : ExtractParentFolder(path);
- }
+ return topFolder;
+ }
- private static bool IsNeedCalculateTopFolder(ChangeType changeType, ItemType itemType)
- {
- return ((changeType.HasFlag(ChangeType.Add)
- || changeType.HasFlag(ChangeType.Branch)
- || changeType.HasFlag(ChangeType.Rename)) && itemType == ItemType.Folder)
- || (itemType == ItemType.File);
+ private static string FindShareFolder(string topFolder, string changeFolder)
+ {
+ // INTACT Tweak based on ihcaesar:branch_not_found PR
+ //if ((topFolder == null) || topFolder.Contains(changeFolder))
+ if ((topFolder == null) || topFolder.IndexOf(changeFolder, StringComparison.OrdinalIgnoreCase) >= 0)
+ {
+ return changeFolder;
+ }
+ const string rootFolder = "$/";
+ var folder = topFolder;
+ while (folder != rootFolder && !changeFolder.StartsWith(folder, StringComparison.OrdinalIgnoreCase))
+ {
+ folder = ExtractParentFolder(folder);
+ if (folder != null && changeFolder.StartsWith(folder, StringComparison.OrdinalIgnoreCase))
+ break;
+ }
+
+ return folder == rootFolder ? folder + "/" : folder;
+ }
- }
+ // private static bool SkipChange(ChangeType changeType, Item item)
+ // {
+ // return changeType.HasFlag(ChangeType.SourceRename) && changeType.HasFlag(ChangeType.Delete);
+ // }
- private static string ExtractParentFolder(string serverItem)
- {
- if (string.IsNullOrWhiteSpace(serverItem))
- throw new ArgumentNullException("serverItem");
+ private static string ExtractFolder(ChangeType changeType, Item item)
+ {
+ return ExtractFolder(changeType, item.ServerItem, item.ItemType);
+ }
- if (serverItem.EndsWith("/"))
- serverItem = serverItem.Substring(0, serverItem.Length - 1);
+ private static string ExtractFolder(ChangeType changeType, string path, ItemType itemType)
+ {
+ if (IsNeedCalculateTopFolder(changeType, itemType))
+ return ExtractParentFolder(path);
- var lastPosDelimiter = serverItem.LastIndexOf('/');
- if (lastPosDelimiter < 0)
- throw new InvalidOperationException(string.Format("Folder delimiter for {0} not found", serverItem));
+ return itemType == ItemType.Folder
+ ? path
+ : ExtractParentFolder(path);
+ }
- return serverItem.Substring(0, lastPosDelimiter + 1);
- }
+ private static bool IsNeedCalculateTopFolder(ChangeType changeType, ItemType itemType)
+ {
+ return ((changeType.HasFlag(ChangeType.Add)
+ || changeType.HasFlag(ChangeType.Branch)
+ || changeType.HasFlag(ChangeType.Rename)) && itemType == ItemType.Folder)
+ || (itemType == ItemType.File);
- private async void MergeExecute(MergeMode? mergeMode)
- {
- Logger.Info("Merging start...");
- if (!mergeMode.HasValue)
- return;
- MergeMode = mergeMode.Value;
- Settings.Instance.LastMergeOperation = mergeMode.Value;
- switch (mergeMode)
- {
- case MergeMode.Merge:
- await MergeAndCheckInExecute(false);
- break;
- case MergeMode.MergeAndCheckIn:
- await MergeAndCheckInExecute(true);
- break;
- }
- Logger.Info("Merging end");
- }
+ }
- private async Task MergeAndCheckInExecute(bool checkInIfSuccess)
- {
- try
- {
- IsBusy = true;
- _merging = true;
+ private static string ExtractParentFolder(string serverItem)
+ {
+ if (string.IsNullOrWhiteSpace(serverItem))
+ throw new ArgumentNullException("serverItem");
- MergeCommand.RaiseCanExecuteChanged();
+ if (serverItem.EndsWith("/"))
+ serverItem = serverItem.Substring(0, serverItem.Length - 1);
- var result = await Task.Run(() => MergeExecuteInternal(checkInIfSuccess));
- var notifications = new List();
- var notCheckedIn = new List(result.Count);
- ClearNotifications();
- foreach (var resultModel in result)
- {
- var notification = new Notification
- {
- NotificationType = NotificationType.Information,
- Message = string.Empty
- };
- var mergePath = string.Format("MERGE {0} -> {1}",
- BranchHelper.GetShortBranchName(resultModel.BranchInfo.SourceBranch),
- BranchHelper.GetShortBranchName(resultModel.BranchInfo.TargetBranch));
- switch (resultModel.MergeResult)
- {
- case MergeResult.CheckInEvaluateFail:
- notification.NotificationType = NotificationType.Error;
- notification.Message = "Check In evaluate failed.";
- notCheckedIn.Add(resultModel);
- break;
- case MergeResult.CheckInFail:
- notification.NotificationType = NotificationType.Error;
- notification.Message = "Check In failed.";
- notCheckedIn.Add(resultModel);
- break;
- case MergeResult.NothingMerge:
- notification.NotificationType = NotificationType.Warning;
- notification.Message = "Nothing merged.";
- break;
- case MergeResult.HasConflicts:
- notification.NotificationType = NotificationType.Error;
- notification.Message = "Has conflicts.";
- notCheckedIn.Add(resultModel);
- break;
- case MergeResult.CanNotGetLatest:
- notification.NotificationType = NotificationType.Error;
- notification.Message = "Can not get latest.";
- break;
- case MergeResult.UnexpectedFileRestored:
- notification.NotificationType = NotificationType.Warning;
- notification.Message = "Some unexpected files were restored.";
- notCheckedIn.Add(resultModel);
- break;
- case MergeResult.Merged:
- notification.NotificationType = NotificationType.Information;
- notification.Message = "Files merged but not checked in.";
- notCheckedIn.Add(resultModel);
- break;
- case MergeResult.CheckIn:
- var changesetId = resultModel.TagetChangesetId.Value;
- notification.NotificationType = NotificationType.Information;
- notification.Message = string.Format("[Changeset {0}](Click to view the changeset details) successfully checked in.", changesetId);
- notification.Command = new DelegateCommand(() => ViewChangesetDetailsExecute(changesetId));
- break;
- }
- notification.Message = string.Format("{0}: {1}", mergePath, notification.Message);
- if (!string.IsNullOrEmpty(notification.Message))
- notifications.Add(notification);
- }
-
- if (notCheckedIn.Count > 0)
- {
- OpenPendingChanges(notCheckedIn);
- }
- else
- {
- _eventAggregator.GetEvent().Publish(true);
- }
+ var lastPosDelimiter = serverItem.LastIndexOf('/');
+ if (lastPosDelimiter < 0)
+ throw new InvalidOperationException(string.Format("Folder delimiter for {0} not found", serverItem));
- foreach (var notification in notifications)
- {
- ShowNotification(notification.Message, notification.NotificationType, NotificationFlags.RequiresConfirmation, notification.Command, Guid.NewGuid());
- }
- }
- catch (Exception ex)
- {
- Logger.Error("Error while merging", ex);
- ClearNotifications();
- ShowError(ex.Message);
- }
- finally
- {
- IsBusy = false;
- _merging = false;
- MergeCommand.RaiseCanExecuteChanged();
- }
+ return serverItem.Substring(0, lastPosDelimiter + 1);
+ }
+
+ private async void MergeExecute(MergeMode? mergeMode)
+ {
+ Logger.Info("Merging start...");
+ if (!mergeMode.HasValue)
+ return;
+ MergeMode = mergeMode.Value;
+ Settings.Instance.LastMergeOperation = mergeMode.Value;
+ switch (mergeMode)
+ {
+ case MergeMode.Merge:
+ await MergeAndCheckInExecute(false);
+ break;
+ case MergeMode.MergeAndCheckIn:
+ await MergeAndCheckInExecute(true);
+ break;
+ }
+ Logger.Info("Merging end");
+ }
+
+ private async Task MergeAndCheckInExecute(bool checkInIfSuccess)
+ {
+ try
+ {
+ IsBusy = true;
+ _merging = true;
+
+ MergeCommand.RaiseCanExecuteChanged();
+
+ var result = await Task.Run(() => MergeExecuteInternal(checkInIfSuccess));
+ var notifications = new List();
+ var notCheckedIn = new List(result.Count);
+ ClearNotifications();
+ foreach (var resultModel in result)
+ {
+ var notification = new Notification
+ {
+ NotificationType = NotificationType.Information,
+ Message = string.Empty
+ };
+ var mergePath = string.Format("MERGE {0} -> {1}",
+ BranchHelper.GetShortBranchName(resultModel.BranchInfo.SourceBranch),
+ BranchHelper.GetShortBranchName(resultModel.BranchInfo.TargetBranch));
+ switch (resultModel.MergeResult)
+ {
+ case MergeResult.CheckInEvaluateFail:
+ notification.NotificationType = NotificationType.Error;
+ notification.Message = "Check In evaluate failed.";
+ notCheckedIn.Add(resultModel);
+ break;
+ case MergeResult.CheckInFail:
+ notification.NotificationType = NotificationType.Error;
+ notification.Message = "Check In failed.";
+ notCheckedIn.Add(resultModel);
+ break;
+ case MergeResult.NothingMerge:
+ notification.NotificationType = NotificationType.Warning;
+ notification.Message = "Nothing merged.";
+ break;
+ case MergeResult.HasConflicts:
+ notification.NotificationType = NotificationType.Error;
+ notification.Message = "Has conflicts.";
+ notCheckedIn.Add(resultModel);
+ break;
+ case MergeResult.CanNotGetLatest:
+ notification.NotificationType = NotificationType.Error;
+ notification.Message = "Can not get latest.";
+ break;
+ case MergeResult.UnexpectedFileRestored:
+ notification.NotificationType = NotificationType.Warning;
+ notification.Message = "Some unexpected files were restored.";
+ notCheckedIn.Add(resultModel);
+ break;
+ case MergeResult.Merged:
+ notification.NotificationType = NotificationType.Information;
+ notification.Message = "Files merged but not checked in.";
+ notCheckedIn.Add(resultModel);
+ break;
+ case MergeResult.CheckIn:
+ var changesetId = resultModel.TagetChangesetId.Value;
+ notification.NotificationType = NotificationType.Information;
+ notification.Message = string.Format("[Changeset {0}](Click to view the changeset details) successfully checked in.", changesetId);
+ notification.Command = new DelegateCommand(() => ViewChangesetDetailsExecute(changesetId));
+ break;
+ }
+ notification.Message = string.Format("{0}: {1}", mergePath, notification.Message);
+ if (!string.IsNullOrEmpty(notification.Message))
+ notifications.Add(notification);
}
- private string ConsolidateDuplicateComments(IEnumerable resultModels)
+ if (notCheckedIn.Count > 0)
{
- return String.Join(";", resultModels.Select(rm => rm.Comment).Distinct());
+ OpenPendingChanges(notCheckedIn);
}
-
- private void OpenPendingChanges(ICollection resultModels)
+ else
{
- var pendingChanges = new List(20);
- // all results must have identical workItems
- var workItemIds = resultModels.First().WorkItemIds;
-
- var conflictsPath = new List();
- foreach (var resultModel in resultModels)
- {
- if (resultModel.PendingChanges != null && resultModel.PendingChanges.Count > 0)
- pendingChanges.AddRange(resultModel.PendingChanges);
-
- if (resultModel.MergeResult == MergeResult.HasConflicts
- || resultModel.MergeResult == MergeResult.UnexpectedFileRestored)
- conflictsPath.Add(resultModel.BranchInfo.TargetPath);
- }
-
- if (conflictsPath.Count > 0)
- InvokeResolveConflictsPage(_workspace, conflictsPath.ToArray());
- OpenPendingChanges(pendingChanges, workItemIds, ConsolidateDuplicateComments(resultModels));
+ _eventAggregator.GetEvent().Publish(true);
}
- private void OpenPendingChanges(List pendingChanges, List workItemIds, string comment)
+ foreach (var notification in notifications)
{
- var teamExplorer = ServiceProvider.GetService();
- var pendingChangesPage = (TeamExplorerPageBase)teamExplorer.NavigateToPage(new Guid(TeamExplorerPageIds.PendingChanges), null);
- var model = (IPendingCheckin)pendingChangesPage.Model;
- model.PendingChanges.Comment = comment;
- model.PendingChanges.CheckedPendingChanges = pendingChanges.ToArray();
-
- if (Workspaces.Count > 1)
- {
- var modelType = model.GetType();
- var workspaceProperty = modelType.GetProperty("Workspace");
- workspaceProperty.SetValue(model, Workspace);
- }
-
- if (workItemIds != null && workItemIds.Count > 0)
- {
- var modelType = model.GetType();
- var method = modelType.GetMethod("AddWorkItemsByIdAsync",
- BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
- var workItemsIdsArray = workItemIds.ToArray();
- method.Invoke(model, new object[] { workItemsIdsArray, 1 /* Add */});
- }
+ ShowNotification(notification.Message, notification.NotificationType, NotificationFlags.RequiresConfirmation, notification.Command, Guid.NewGuid());
}
+ }
+ catch (Exception ex)
+ {
+ Logger.Error("Error while merging", ex);
+ ClearNotifications();
+ ShowError(ex.Message);
+ }
+ finally
+ {
+ IsBusy = false;
+ _merging = false;
+ MergeCommand.RaiseCanExecuteChanged();
+ }
+ }
- private List MergeExecuteInternal(bool checkInIfSuccess)
- {
- var result = new List();
- var context = Context;
- var tfs = context.TeamProjectCollection;
- var versionControl = tfs.GetService();
-
- var workspace = _workspace;
-
- var changesetId = _changeset.ChangesetId;
- var changesetService = _changesetService;
- var changeset = changesetService.GetChangeset(changesetId);
- changeset.Changes = changesetService.GetChanges(changesetId);
- var mergeOption = _mergeOption;
- var workItemStore = tfs.GetService();
- var workItemIds = changeset.AssociatedWorkItems != null
- ? changeset.AssociatedWorkItems.Select(w => w.Id).ToList()
- : new List();
-
- var mergeInfos = _branches;
- var targetBranches = mergeInfos.Select(m => m.TargetBranch).ToArray();
- var pendingChanges = GetChangesetPendingChanges(changeset.Changes);
- var mergeRelationships = GetMergeRelationships(pendingChanges, targetBranches, versionControl);
-
- var commentFormater = new CommentFormater(Settings.Instance.CommentFormat);
- foreach (var mergeInfo in mergeInfos.Where(b => b.Checked))
- {
- var mergeResultModel = new MergeResultModel
- {
- SourceChangesetId = changesetId,
- BranchInfo = mergeInfo,
- };
+ private string ConsolidateDuplicateComments(IEnumerable resultModels)
+ {
+ return String.Join(";", resultModels.Select(rm => rm.Comment).Distinct());
+ }
- var mergeResult = MergeToBranch(mergeInfo, mergeOption, mergeRelationships, workspace);
- var targetPendingChanges = GetPendingChanges(mergeInfo.TargetPath, workspace);
- if (mergeResult == MergeResult.UnexpectedFileRestored)
- {
- workspace.Undo(targetPendingChanges.Select(pendingChange => new ItemSpec(pendingChange)).ToArray(),
- true);
- mergeResult = MergeByFile(changeset.Changes, mergeInfo.TargetBranch, mergeRelationships,
- mergeInfo.ChangesetVersionSpec, mergeOption, workspace);
- targetPendingChanges = GetPendingChangesByFile(mergeRelationships, mergeInfo.TargetBranch, workspace);
- }
-
- if (targetPendingChanges.Count == 0)
- {
- mergeResult = MergeResult.NothingMerge;
- }
- mergeResultModel.MergeResult = mergeResult;
- mergeResultModel.PendingChanges = targetPendingChanges;
- mergeResultModel.WorkItemIds = workItemIds;
-
- var trackMergeInfo = GetTrackMergeInfo(mergeInfo, changeset, versionControl);
- var comment = commentFormater.Format(trackMergeInfo, mergeInfo.TargetBranch, mergeOption);
- mergeResultModel.Comment = comment;
-
- result.Add(mergeResultModel);
- if (checkInIfSuccess && mergeResultModel.MergeResult == MergeResult.Merged)
- {
- var checkInResult = CheckIn(mergeResultModel.PendingChanges, comment, workspace, workItemIds, changeset.PolicyOverride, workItemStore);
- mergeResultModel.TagetChangesetId = checkInResult.ChangesetId;
- mergeResultModel.MergeResult = checkInResult.CheckinResult;
- }
- }
+ private void OpenPendingChanges(ICollection resultModels)
+ {
+ var pendingChanges = new List(20);
+ // all results must have identical workItems
+ var workItemIds = resultModels.First().WorkItemIds;
+
+ var conflictsPath = new List();
+ foreach (var resultModel in resultModels)
+ {
+ if (resultModel.PendingChanges != null && resultModel.PendingChanges.Count > 0)
+ pendingChanges.AddRange(resultModel.PendingChanges);
+
+ if (resultModel.MergeResult == MergeResult.HasConflicts
+ || resultModel.MergeResult == MergeResult.UnexpectedFileRestored)
+ conflictsPath.Add(resultModel.BranchInfo.TargetPath);
+ }
+
+ if (conflictsPath.Count > 0)
+ InvokeResolveConflictsPage(_workspace, conflictsPath.ToArray());
+ OpenPendingChanges(pendingChanges, workItemIds, ConsolidateDuplicateComments(resultModels));
+ }
- return result;
- }
+ private void OpenPendingChanges(List pendingChanges, List workItemIds, string comment)
+ {
+ var teamExplorer = ServiceProvider.GetService();
+ var pendingChangesPage = (TeamExplorerPageBase)teamExplorer.NavigateToPage(new Guid(TeamExplorerPageIds.PendingChanges), null);
+ var model = (IPendingCheckin)pendingChangesPage.Model;
+ model.PendingChanges.Comment = comment;
+ model.PendingChanges.CheckedPendingChanges = pendingChanges.ToArray();
+
+ if (Workspaces.Count > 1)
+ {
+ var modelType = model.GetType();
+ var workspaceProperty = modelType.GetProperty("Workspace");
+ workspaceProperty.SetValue(model, Workspace);
+ }
+
+ if (workItemIds != null && workItemIds.Count > 0)
+ {
+ var modelType = model.GetType();
+ var method = modelType.GetMethod("AddWorkItemsByIdAsync",
+ BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
+ var workItemsIdsArray = workItemIds.ToArray();
+ method.Invoke(model, new object[] { workItemsIdsArray, 1 /* Add */});
+ }
+ }
- // Copy from Microsoft.TeamFoundation.VersionControl.Controls.PendingChanges.ChangesetDataProvider.ResetDataFromChangeset,
- // Microsoft.TeamFoundation.VersionControl.Controls
- private static List GetChangesetPendingChanges(Change[] changes)
+ private List MergeExecuteInternal(bool checkInIfSuccess)
+ {
+ var result = new List();
+ var context = Context;
+ var tfs = context.TeamProjectCollection;
+ var versionControl = tfs.GetService();
+
+ var workspace = _workspace;
+
+ var changesetId = _changeset.ChangesetId;
+ var changesetService = _changesetService;
+ var changeset = changesetService.GetChangeset(changesetId);
+ changeset.Changes = changesetService.GetChanges(changesetId);
+ var mergeOption = _mergeOption;
+ var workItemStore = tfs.GetService();
+ var workItemIds = changeset.AssociatedWorkItems != null
+ ? changeset.AssociatedWorkItems.Select(w => w.Id).ToList()
+ : new List();
+
+ var mergeInfos = _branches;
+ var targetBranches = mergeInfos.Select(m => m.TargetBranch).ToArray();
+ var pendingChanges = GetChangesetPendingChanges(changeset.Changes);
+ var mergeRelationships = GetMergeRelationships(pendingChanges, targetBranches, versionControl);
+
+ var commentFormater = new CommentFormater(Settings.Instance.CommentFormat);
+ foreach (var mergeInfo in mergeInfos.Where(b => b.Checked))
+ {
+ var mergeResultModel = new MergeResultModel
{
- var pendingChanges = new List(changes.Length);
- foreach (var change in changes)
- {
- if (ChangeType.SourceRename != (change.ChangeType & (ChangeType.Add | ChangeType.Branch | ChangeType.Rename | ChangeType.SourceRename)))
- {
- var pendingChange = new PendingChange(change);
- if (change.MergeSources != null)
- {
- foreach (var mergeSource in change.MergeSources)
- {
- if (mergeSource.IsRename)
- {
- pendingChange.UpdateSourceItems(null, mergeSource.ServerItem);
- break;
- }
- }
- }
- pendingChanges.Add(pendingChange);
- }
- }
+ SourceChangesetId = changesetId,
+ BranchInfo = mergeInfo,
+ };
- return pendingChanges;
+ var mergeResult = MergeToBranch(mergeInfo, mergeOption, mergeRelationships, workspace);
+ var targetPendingChanges = GetPendingChanges(mergeInfo.TargetPath, workspace);
+ if (mergeResult == MergeResult.UnexpectedFileRestored)
+ {
+ workspace.Undo(targetPendingChanges.Select(pendingChange => new ItemSpec(pendingChange)).ToArray(),
+ true);
+ mergeResult = MergeByFile(changeset.Changes, mergeInfo.TargetBranch, mergeRelationships,
+ mergeInfo.ChangesetVersionSpec, mergeOption, workspace);
+ targetPendingChanges = GetPendingChangesByFile(mergeRelationships, mergeInfo.TargetBranch, workspace);
}
- private static List GetMergeRelationships(List pendingChanges, string[] targetBranches, VersionControlServer versionControl)
+ if (targetPendingChanges.Count == 0)
{
- var mergeRelationships = new List();
-
- foreach (var pendingChange in pendingChanges)
- {
- if (pendingChange.IsAdd || pendingChange.IsBranch)
- {
- var parentFolder = ExtractFolder(pendingChange.ChangeType, pendingChange.ServerItem, pendingChange.ItemType);
- var parentFolderRelationships = versionControl.QueryMergeRelationships(parentFolder);
- if (parentFolderRelationships != null)
- {
- foreach (var parentFolderRelationship in parentFolderRelationships.Where(r => !r.IsDeleted))
- {
- mergeRelationships.Add(new MergeRelation
- {
- Item = pendingChange.ServerItem,
- Source = parentFolder,
- Target = parentFolderRelationship.Item,
- TargetItemType = ItemType.Folder,
- GetLatesPath = parentFolderRelationship.Item,
- Recursively = pendingChange.ItemType == ItemType.Folder
- });
- }
- }
- }
- else if (pendingChange.IsRename)
- {
- var shareFolder = FindShareFolder(pendingChange.ServerItem, pendingChange.SourceServerItem);
- var shareFolderRelationships = versionControl.QueryMergeRelationships(shareFolder);
- var sourceRelationships = versionControl.QueryMergeRelationships(pendingChange.SourceServerItem) ?? new ItemIdentifier[0];
- if (shareFolderRelationships != null)
- {
- foreach (var shareFolderRelationship in shareFolderRelationships.Where(r => !r.IsDeleted))
- {
- // INTACT Tweak based on ihcaesar:branch_not_found PR
- var targetBranch =
- //targetBranches.FirstOrDefault(branch => shareFolderRelationship.Item.Contains(branch));
- targetBranches.FirstOrDefault(branch => shareFolderRelationship.Item.IndexOf(branch, StringComparison.OrdinalIgnoreCase) >= 0);
- if (targetBranch != null)
- {
- // INTACT Tweak based on ihcaesar:branch_not_found PR
- var sourceRelationship = sourceRelationships
- //.FirstOrDefault(r => r.Item.Contains(targetBranch));
- .FirstOrDefault(r => r.Item.IndexOf(targetBranch, StringComparison.OrdinalIgnoreCase) >= 0);
- mergeRelationships.Add(new MergeRelation
- {
- Item = pendingChange.ServerItem,
- Source = shareFolder,
- Target = shareFolderRelationship.Item,
- TargetItemType = ItemType.Folder,
- GetLatesPath = sourceRelationship != null ? sourceRelationship.Item : null,
- Recursively = true
- });
- }
- }
- }
- }
- else
- {
- var changeRelationShips = versionControl.QueryMergeRelationships(pendingChange.ServerItem);
- if (changeRelationShips != null)
- {
- foreach (var changeRelationShip in changeRelationShips.Where(r => !r.IsDeleted))
- {
- mergeRelationships.Add(new MergeRelation
- {
- Item = pendingChange.ServerItem,
- Source = pendingChange.ServerItem,
- Target = changeRelationShip.Item,
- TargetItemType = pendingChange.ItemType,
- GetLatesPath = changeRelationShip.Item
- });
- }
- }
- }
- }
- return mergeRelationships;
+ mergeResult = MergeResult.NothingMerge;
}
+ mergeResultModel.MergeResult = mergeResult;
+ mergeResultModel.PendingChanges = targetPendingChanges;
+ mergeResultModel.WorkItemIds = workItemIds;
+ var trackMergeInfo = GetTrackMergeInfo(mergeInfo, changeset, versionControl);
+ var comment = commentFormater.Format(trackMergeInfo, mergeInfo.TargetBranch, mergeOption);
+ mergeResultModel.Comment = comment;
- private TrackMergeInfo GetTrackMergeInfo(MergeInfoViewModel mergeInfo, Changeset changeset, VersionControlServer versionControl)
+ result.Add(mergeResultModel);
+ if (checkInIfSuccess && mergeResultModel.MergeResult == MergeResult.Merged)
{
- var mergesRelationships = GetMergesRelationships(mergeInfo.SourcePath, versionControl);
- var trackMerges = versionControl.TrackMerges(new[] {changeset.ChangesetId},
- new ItemIdentifier(mergeInfo.SourcePath),
- mergesRelationships.ToArray(),
- null);
-
- var trackMergeInfo = GetTrackMergeInfo(versionControl,
- trackMerges, mergeInfo.SourcePath);
- trackMergeInfo.FromOriginalToSourceBranches.Reverse();
- trackMergeInfo.SourceComment = changeset.Comment;
- trackMergeInfo.SourceBranch = mergeInfo.SourceBranch;
- trackMergeInfo.SourceChangesetId = changeset.ChangesetId;
- trackMergeInfo.SourceWorkItemIds = changeset.AssociatedWorkItems != null
- ? changeset.AssociatedWorkItems.Select(w => (long) w.Id).ToList()
- : new List(0);
- trackMergeInfo.SourceWorkItemTitles = changeset.AssociatedWorkItems != null
- ? changeset.AssociatedWorkItems.Select(w => w.Title).ToList()
- : new List(0);
- trackMergeInfo.OriginaBranch = trackMergeInfo.OriginaBranch ?? trackMergeInfo.SourceBranch;
- trackMergeInfo.OriginalComment = trackMergeInfo.OriginalComment ?? trackMergeInfo.SourceComment;
- return trackMergeInfo;
+ var checkInResult = CheckIn(mergeResultModel.PendingChanges, comment, workspace, workItemIds, changeset.PolicyOverride, workItemStore);
+ mergeResultModel.TagetChangesetId = checkInResult.ChangesetId;
+ mergeResultModel.MergeResult = checkInResult.CheckinResult;
}
+ }
- private static CheckInResult CheckIn(IReadOnlyCollection targetPendingChanges, string comment,
- Workspace workspace, IReadOnlyCollection workItemIds, PolicyOverrideInfo policyOverride, WorkItemStore workItemStore)
- {
- var result = new CheckInResult();
+ return result;
+ }
- // Another user can update workitem. Need re-read before update.
- var workItems = GetWorkItemCheckinInfo(workItemIds, workItemStore);
+ // Copy from Microsoft.TeamFoundation.VersionControl.Controls.PendingChanges.ChangesetDataProvider.ResetDataFromChangeset,
+ // Microsoft.TeamFoundation.VersionControl.Controls
+ private static List GetChangesetPendingChanges(Change[] changes)
+ {
+ var pendingChanges = new List(changes.Length);
+ foreach (var change in changes)
+ {
+ if (ChangeType.SourceRename != (change.ChangeType & (ChangeType.Add | ChangeType.Branch | ChangeType.Rename | ChangeType.SourceRename)))
+ {
+ var pendingChange = new PendingChange(change);
+ if (change.MergeSources != null)
+ {
+ foreach (var mergeSource in change.MergeSources)
+ {
+ if (mergeSource.IsRename)
+ {
+ pendingChange.UpdateSourceItems(null, mergeSource.ServerItem);
+ break;
+ }
+ }
+ }
+ pendingChanges.Add(pendingChange);
+ }
+ }
- var evaluateCheckIn = workspace.EvaluateCheckin2(CheckinEvaluationOptions.All,
- targetPendingChanges,
- comment,
- null,
- workItems);
+ return pendingChanges;
+ }
- var skipPolicyValidate = !policyOverride.PolicyFailures.IsNullOrEmpty();
- if (!CanCheckIn(evaluateCheckIn, skipPolicyValidate))
- {
- result.CheckinResult = MergeResult.CheckInEvaluateFail;
- return result;
- }
+ private static List GetMergeRelationships(List pendingChanges, string[] targetBranches, VersionControlServer versionControl)
+ {
+ var mergeRelationships = new List();
- var changesetId = workspace.CheckIn(targetPendingChanges.ToArray(), null, comment,
- null, workItems, policyOverride);
- if (changesetId > 0)
- {
- result.ChangesetId = changesetId;
- result.CheckinResult = MergeResult.CheckIn;
- }
- else
- {
- result.CheckinResult = MergeResult.CheckInFail;
+ foreach (var pendingChange in pendingChanges)
+ {
+ if (pendingChange.IsAdd || pendingChange.IsBranch)
+ {
+ var parentFolder = ExtractFolder(pendingChange.ChangeType, pendingChange.ServerItem, pendingChange.ItemType);
+ var parentFolderRelationships = versionControl.QueryMergeRelationships(parentFolder);
+ if (parentFolderRelationships != null)
+ {
+ foreach (var parentFolderRelationship in parentFolderRelationships.Where(r => !r.IsDeleted))
+ {
+ mergeRelationships.Add(new MergeRelation
+ {
+ Item = pendingChange.ServerItem,
+ Source = parentFolder,
+ Target = parentFolderRelationship.Item,
+ TargetItemType = ItemType.Folder,
+ GetLatesPath = parentFolderRelationship.Item,
+ Recursively = pendingChange.ItemType == ItemType.Folder
+ });
}
- return result;
+ }
}
-
- private MergeResult MergeByFile(Change[] changes, string targetBranch, List mergeRelationships,
- VersionSpec version, MergeOption mergeOption, Workspace workspace)
+ else if (pendingChange.IsRename)
{
- if (!GetLatest(targetBranch, mergeRelationships, workspace))
- {
- return MergeResult.CanNotGetLatest;
- }
-
- var mergeOptions = ToTfsMergeOptions(mergeOption);
- var hasConflicts = false;
- foreach (var change in changes)
- {
+ var shareFolder = FindShareFolder(pendingChange.ServerItem, pendingChange.SourceServerItem);
+ var shareFolderRelationships = versionControl.QueryMergeRelationships(shareFolder);
+ var sourceRelationships = versionControl.QueryMergeRelationships(pendingChange.SourceServerItem) ?? new ItemIdentifier[0];
+ if (shareFolderRelationships != null)
+ {
+ foreach (var shareFolderRelationship in shareFolderRelationships.Where(r => !r.IsDeleted))
+ {
+ // INTACT Tweak based on ihcaesar:branch_not_found PR
+ var targetBranch =
+ //targetBranches.FirstOrDefault(branch => shareFolderRelationship.Item.Contains(branch));
+ targetBranches.FirstOrDefault(branch => shareFolderRelationship.Item.IndexOf(branch, StringComparison.OrdinalIgnoreCase) >= 0);
+ if (targetBranch != null)
+ {
// INTACT Tweak based on ihcaesar:branch_not_found PR
- var mergeRelation =
- mergeRelationships.FirstOrDefault(
- //r => r.Item == change.Item.ServerItem && r.Target.StartsWith(targetBranch));
- r => r.Item == change.Item.ServerItem && r.Target.StartsWith(targetBranch, StringComparison.OrdinalIgnoreCase));
- if (mergeRelation != null)
- {
- var recursionType = CalculateRecursionType(mergeRelation);
- var status = workspace.Merge(mergeRelation.Source, mergeRelation.Target, version, version,
- LockLevel.None, recursionType, mergeOptions);
- if (!hasConflicts && HasConflicts(status))
- {
- hasConflicts = true;
- }
- }
- else
+ var sourceRelationship = sourceRelationships
+ //.FirstOrDefault(r => r.Item.Contains(targetBranch));
+ .FirstOrDefault(r => r.Item.IndexOf(targetBranch, StringComparison.OrdinalIgnoreCase) >= 0);
+ mergeRelationships.Add(new MergeRelation
{
- Logger.Info("File {0} not merged to branch {1}", change.Item.ServerItem, targetBranch);
- }
+ Item = pendingChange.ServerItem,
+ Source = shareFolder,
+ Target = shareFolderRelationship.Item,
+ TargetItemType = ItemType.Folder,
+ GetLatesPath = sourceRelationship != null ? sourceRelationship.Item : null,
+ Recursively = true
+ });
+ }
}
-
- if (hasConflicts)
- {
- var conflicts = AutoResolveConflicts(workspace, targetBranch, mergeOption);
- if (!conflicts.IsNullOrEmpty())
- {
- return IsTryRestoreUnexpectedFile(conflicts)
- ? MergeResult.UnexpectedFileRestored
- : MergeResult.HasConflicts;
- }
+ }
+ }
+ else
+ {
+ var changeRelationShips = versionControl.QueryMergeRelationships(pendingChange.ServerItem);
+ if (changeRelationShips != null)
+ {
+ foreach (var changeRelationShip in changeRelationShips.Where(r => !r.IsDeleted))
+ {
+ mergeRelationships.Add(new MergeRelation
+ {
+ Item = pendingChange.ServerItem,
+ Source = pendingChange.ServerItem,
+ Target = changeRelationShip.Item,
+ TargetItemType = pendingChange.ItemType,
+ GetLatesPath = changeRelationShip.Item
+ });
}
-
- return MergeResult.Merged;
+ }
}
+ }
+ return mergeRelationships;
+ }
- private static MergeResult MergeToBranch(MergeInfoViewModel mergeInfoeViewModel, MergeOption mergeOption,
- List mergeRelationships, Workspace workspace)
- {
- var source = mergeInfoeViewModel.SourcePath;
- var target = mergeInfoeViewModel.TargetPath;
- var version = mergeInfoeViewModel.ChangesetVersionSpec;
- if (!GetLatest(target, mergeRelationships, workspace))
- {
- return MergeResult.CanNotGetLatest;
- }
+ private TrackMergeInfo GetTrackMergeInfo(MergeInfoViewModel mergeInfo, Changeset changeset, VersionControlServer versionControl)
+ {
+ var mergesRelationships = GetMergesRelationships(mergeInfo.SourcePath, versionControl);
+ var trackMerges = versionControl.TrackMerges(new[] { changeset.ChangesetId },
+ new ItemIdentifier(mergeInfo.SourcePath),
+ mergesRelationships.ToArray(),
+ null);
+
+ var trackMergeInfo = GetTrackMergeInfo(versionControl,
+ trackMerges, mergeInfo.SourcePath);
+ trackMergeInfo.FromOriginalToSourceBranches.Reverse();
+ trackMergeInfo.SourceComment = changeset.Comment;
+ trackMergeInfo.SourceBranch = mergeInfo.SourceBranch;
+ trackMergeInfo.SourceChangesetId = changeset.ChangesetId;
+ trackMergeInfo.SourceWorkItemIds = changeset.AssociatedWorkItems != null
+ ? changeset.AssociatedWorkItems.Select(w => (long)w.Id).ToList()
+ : new List(0);
+ trackMergeInfo.SourceWorkItemTitles = changeset.AssociatedWorkItems != null
+ ? changeset.AssociatedWorkItems.Select(w => w.Title).ToList()
+ : new List(0);
+ trackMergeInfo.OriginaBranch = trackMergeInfo.OriginaBranch ?? trackMergeInfo.SourceBranch;
+ trackMergeInfo.OriginalComment = trackMergeInfo.OriginalComment ?? trackMergeInfo.SourceComment;
+ return trackMergeInfo;
+ }
- var mergeOptions = ToTfsMergeOptions(mergeOption);
- var status = workspace.Merge(source, target, version, version, LockLevel.None, RecursionType.Full, mergeOptions);
- if (HasConflicts(status))
- {
- var conflicts = AutoResolveConflicts(workspace, target, mergeOption);
- if (!conflicts.IsNullOrEmpty())
- {
- return IsTryRestoreUnexpectedFile(conflicts)
- ? MergeResult.UnexpectedFileRestored
- : MergeResult.HasConflicts;
- }
- }
+ private static CheckInResult CheckIn(IReadOnlyCollection targetPendingChanges, string comment,
+ Workspace workspace, IReadOnlyCollection workItemIds, PolicyOverrideInfo policyOverride, WorkItemStore workItemStore)
+ {
+ var result = new CheckInResult();
+
+ // Another user can update workitem. Need re-read before update.
+ var workItems = GetWorkItemCheckinInfo(workItemIds, workItemStore);
+
+ var evaluateCheckIn = workspace.EvaluateCheckin2(CheckinEvaluationOptions.All,
+ targetPendingChanges,
+ comment,
+ null,
+ workItems);
+
+ var skipPolicyValidate = !policyOverride.PolicyFailures.IsNullOrEmpty();
+ if (!CanCheckIn(evaluateCheckIn, skipPolicyValidate))
+ {
+ result.CheckinResult = MergeResult.CheckInEvaluateFail;
+ return result;
+ }
+
+ var changesetId = workspace.CheckIn(targetPendingChanges.ToArray(), null, comment,
+ null, workItems, policyOverride);
+ if (changesetId > 0)
+ {
+ result.ChangesetId = changesetId;
+ result.CheckinResult = MergeResult.CheckIn;
+ }
+ else
+ {
+ result.CheckinResult = MergeResult.CheckInFail;
+ }
+ return result;
+ }
- return MergeResult.Merged;
+ private MergeResult MergeByFile(Change[] changes, string targetBranch, List mergeRelationships,
+ VersionSpec version, MergeOption mergeOption, Workspace workspace)
+ {
+ if (!GetLatest(targetBranch, mergeRelationships, workspace))
+ {
+ return MergeResult.CanNotGetLatest;
+ }
+
+ var mergeOptions = ToTfsMergeOptions(mergeOption);
+ var hasConflicts = false;
+ foreach (var change in changes)
+ {
+ // INTACT Tweak based on ihcaesar:branch_not_found PR
+ var mergeRelation =
+ mergeRelationships.FirstOrDefault(
+ //r => r.Item == change.Item.ServerItem && r.Target.StartsWith(targetBranch));
+ r => r.Item == change.Item.ServerItem && r.Target.StartsWith(targetBranch, StringComparison.OrdinalIgnoreCase));
+ if (mergeRelation != null)
+ {
+ var recursionType = CalculateRecursionType(mergeRelation);
+ var status = workspace.Merge(mergeRelation.Source, mergeRelation.Target, version, version,
+ LockLevel.None, recursionType, mergeOptions);
+ if (!hasConflicts && HasConflicts(status))
+ {
+ hasConflicts = true;
+ }
}
-
- private static bool IsTryRestoreUnexpectedFile(Conflict[] conflicts)
+ else
{
- foreach (var conflict in conflicts)
- {
- if (conflict.BaseChangeType.HasFlag(ChangeType.Undelete)
- && !conflict.TheirChangeType.HasFlag(ChangeType.Undelete))
- {
- return true;
- }
- }
-
- return false;
+ Logger.Info("File {0} not merged to branch {1}", change.Item.ServerItem, targetBranch);
}
+ }
- private static List GetPendingChanges(string target, Workspace workspace)
+ if (hasConflicts)
+ {
+ var conflicts = AutoResolveConflicts(workspace, targetBranch, mergeOption);
+ if (!conflicts.IsNullOrEmpty())
{
- var allPendingChanges = workspace.GetPendingChangesEnumerable(target, RecursionType.Full);
-
- // INTACT Tweak based on ihcaesar:branch_not_found PR
- var targetPendingChanges = allPendingChanges
- //.Where(p => p.IsMerge && p.ServerItem.Contains(target))
- .Where(p => p.IsMerge && p.ServerItem.IndexOf(target, StringComparison.OrdinalIgnoreCase) >= 0)
- .ToList();
-
- return targetPendingChanges;
+ return IsTryRestoreUnexpectedFile(conflicts)
+ ? MergeResult.UnexpectedFileRestored
+ : MergeResult.HasConflicts;
}
+ }
+
+ return MergeResult.Merged;
+ }
- private static List GetPendingChangesByFile(List mergeRelationships, string targetBranch, Workspace workspace)
+ private static MergeResult MergeToBranch(MergeInfoViewModel mergeInfoeViewModel, MergeOption mergeOption,
+ List mergeRelationships, Workspace workspace)
+ {
+ var source = mergeInfoeViewModel.SourcePath;
+ var target = mergeInfoeViewModel.TargetPath;
+ var version = mergeInfoeViewModel.ChangesetVersionSpec;
+
+ if (!GetLatest(target, mergeRelationships, workspace))
+ {
+ return MergeResult.CanNotGetLatest;
+ }
+
+ var mergeOptions = ToTfsMergeOptions(mergeOption);
+ var status = workspace.Merge(source, target, version, version, LockLevel.None, RecursionType.Full, mergeOptions);
+ if (HasConflicts(status))
+ {
+ var conflicts = AutoResolveConflicts(workspace, target, mergeOption);
+ if (!conflicts.IsNullOrEmpty())
{
- var itemSpecs = new List();
- foreach (var mergeRelationship in mergeRelationships)
- {
- // INTACT Tweak based on ihcaesar:branch_not_found PR
- //if (mergeRelationship.Target.StartsWith(targetBranch))
- if (mergeRelationship.Target.StartsWith(targetBranch, StringComparison.OrdinalIgnoreCase))
- {
- var recursionType = CalculateRecursionType(mergeRelationship);
- itemSpecs.Add(new ItemSpec(mergeRelationship.Target, recursionType));
- }
- }
- return workspace.GetPendingChanges(itemSpecs.ToArray()).ToList();
+ return IsTryRestoreUnexpectedFile(conflicts)
+ ? MergeResult.UnexpectedFileRestored
+ : MergeResult.HasConflicts;
}
+ }
+
+ return MergeResult.Merged;
+ }
- private static RecursionType CalculateRecursionType(MergeRelation mergeRelationship)
+ private static bool IsTryRestoreUnexpectedFile(Conflict[] conflicts)
+ {
+ foreach (var conflict in conflicts)
+ {
+ if (conflict.BaseChangeType.HasFlag(ChangeType.Undelete)
+ && !conflict.TheirChangeType.HasFlag(ChangeType.Undelete))
{
- var recursionType = mergeRelationship.Recursively
- ? RecursionType.Full
- : mergeRelationship.TargetItemType == ItemType.File
- ? RecursionType.None
- : RecursionType.OneLevel;
- return recursionType;
+ return true;
}
+ }
- private static bool GetLatest(string targetPath, List mergeRelationships, Workspace workspace)
- {
- var getLatestFiles = new List();
- foreach (var mergeRelationship in mergeRelationships.Where(r => r.TargetItemType == ItemType.File && r.GetLatesPath != null))
- {
- // INTACT Tweak based on ihcaesar:branch_not_found PR
- if (mergeRelationship.GetLatesPath.StartsWith(targetPath, StringComparison.OrdinalIgnoreCase))
- //if (mergeRelationship.GetLatesPath.StartsWith(targetPath))
- getLatestFiles.Add(mergeRelationship.GetLatesPath);
- }
+ return false;
+ }
- var getLatestFilesArray = getLatestFiles.ToArray();
- if (getLatestFilesArray.Length > 0)
- {
- const RecursionType recursionType = RecursionType.None;
- var getLatestResult = workspace.Get(getLatestFilesArray, VersionSpec.Latest, recursionType, GetOptions.None);
- if (!getLatestResult.NoActionNeeded)
- {
- // HACK.
- getLatestResult = workspace.Get(getLatestFilesArray, VersionSpec.Latest, recursionType, GetOptions.None);
- if (!getLatestResult.NoActionNeeded)
- {
- return false;
- }
- }
- }
+ private static List GetPendingChanges(string target, Workspace workspace)
+ {
+ var allPendingChanges = workspace.GetPendingChangesEnumerable(target, RecursionType.Full);
- return true;
- }
+ // INTACT Tweak based on ihcaesar:branch_not_found PR
+ var targetPendingChanges = allPendingChanges
+ //.Where(p => p.IsMerge && p.ServerItem.Contains(target))
+ .Where(p => p.IsMerge && p.ServerItem.IndexOf(target, StringComparison.OrdinalIgnoreCase) >= 0)
+ .ToList();
- private static MergeOptionsEx ToTfsMergeOptions(MergeOption mergeOption)
- {
- switch (mergeOption)
- {
- case MergeOption.KeepTarget:
- return MergeOptionsEx.AlwaysAcceptMine;
- default:
- return MergeOptionsEx.None;
- }
- }
+ return targetPendingChanges;
+ }
- public bool MergeCanEcexute()
+ private static List GetPendingChangesByFile(List mergeRelationships, string targetBranch, Workspace workspace)
+ {
+ var itemSpecs = new List();
+ foreach (var mergeRelationship in mergeRelationships)
+ {
+ // INTACT Tweak based on ihcaesar:branch_not_found PR
+ //if (mergeRelationship.Target.StartsWith(targetBranch))
+ if (mergeRelationship.Target.StartsWith(targetBranch, StringComparison.OrdinalIgnoreCase))
{
- return !_merging && _branches != null && _branches.Any(b => b.Checked);
+ var recursionType = CalculateRecursionType(mergeRelationship);
+ itemSpecs.Add(new ItemSpec(mergeRelationship.Target, recursionType));
}
+ }
+ return workspace.GetPendingChanges(itemSpecs.ToArray()).ToList();
+ }
- private static bool HasConflicts(GetStatus mergeStatus)
+ private static RecursionType CalculateRecursionType(MergeRelation mergeRelationship)
+ {
+ var recursionType = mergeRelationship.Recursively
+ ? RecursionType.Full
+ : mergeRelationship.TargetItemType == ItemType.File
+ ? RecursionType.None
+ : RecursionType.OneLevel;
+ return recursionType;
+ }
+
+ private static bool GetLatest(string targetPath, List mergeRelationships, Workspace workspace)
+ {
+ var getLatestFiles = new List();
+ foreach (var mergeRelationship in mergeRelationships.Where(r => r.TargetItemType == ItemType.File && r.GetLatesPath != null))
+ {
+ // INTACT Tweak based on ihcaesar:branch_not_found PR
+ if (mergeRelationship.GetLatesPath.StartsWith(targetPath, StringComparison.OrdinalIgnoreCase))
+ //if (mergeRelationship.GetLatesPath.StartsWith(targetPath))
+ getLatestFiles.Add(mergeRelationship.GetLatesPath);
+ }
+
+ var getLatestFilesArray = getLatestFiles.ToArray();
+ if (getLatestFilesArray.Length > 0)
+ {
+ const RecursionType recursionType = RecursionType.None;
+ var getLatestResult = workspace.Get(getLatestFilesArray, VersionSpec.Latest, recursionType, GetOptions.None);
+ if (!getLatestResult.NoActionNeeded)
{
- return !mergeStatus.NoActionNeeded && mergeStatus.NumConflicts > 0;
+ // HACK.
+ getLatestResult = workspace.Get(getLatestFilesArray, VersionSpec.Latest, recursionType, GetOptions.None);
+ if (!getLatestResult.NoActionNeeded)
+ {
+ return false;
+ }
}
+ }
- private static Conflict[] AutoResolveConflicts(Workspace workspace, string targetPath, MergeOption mergeOption)
- {
- var targetPaths = new[] {targetPath};
- var conflicts = workspace.QueryConflicts(targetPaths, true);
- if (conflicts.IsNullOrEmpty())
- return null;
+ return true;
+ }
- foreach (var conflict in conflicts)
- {
- TryResolve(workspace, conflict, mergeOption);
- }
+ private static MergeOptionsEx ToTfsMergeOptions(MergeOption mergeOption)
+ {
+ switch (mergeOption)
+ {
+ case MergeOption.KeepTarget:
+ return MergeOptionsEx.AlwaysAcceptMine;
+ default:
+ return MergeOptionsEx.None;
+ }
+ }
- conflicts = workspace.QueryConflicts(targetPaths, true);
- if (conflicts.IsNullOrEmpty())
- return null;
+ public bool MergeCanEcexute()
+ {
+ return !_merging && _branches != null && _branches.Any(b => b.Checked);
+ }
- workspace.AutoResolveValidConflicts(conflicts, AutoResolveOptions.AllSilent);
+ private static bool HasConflicts(GetStatus mergeStatus)
+ {
+ return !mergeStatus.NoActionNeeded && mergeStatus.NumConflicts > 0;
+ }
- return workspace.QueryConflicts(targetPaths, true);
- }
+ private static Conflict[] AutoResolveConflicts(Workspace workspace, string targetPath, MergeOption mergeOption)
+ {
+ var targetPaths = new[] { targetPath };
+ var conflicts = workspace.QueryConflicts(targetPaths, true);
+ if (conflicts.IsNullOrEmpty())
+ return null;
- private static void TryResolve(Workspace workspace, Conflict conflict, MergeOption mergeOption)
- {
- if (mergeOption == MergeOption.KeepTarget)
- {
- conflict.Resolution = Resolution.AcceptYours;
- workspace.ResolveConflict(conflict);
- }
- if (mergeOption == MergeOption.OverwriteTarget)
- {
- conflict.Resolution = Resolution.AcceptTheirs;
- workspace.ResolveConflict(conflict);
- }
- }
+ foreach (var conflict in conflicts)
+ {
+ TryResolve(workspace, conflict, mergeOption);
+ }
+ conflicts = workspace.QueryConflicts(targetPaths, true);
+ if (conflicts.IsNullOrEmpty())
+ return null;
- private static WorkItemCheckinInfo[] GetWorkItemCheckinInfo(IReadOnlyCollection workItemIds, WorkItemStore workItemStore)
- {
+ workspace.AutoResolveValidConflicts(conflicts, AutoResolveOptions.AllSilent);
- var result = new List(workItemIds.Count);
- foreach (var workItemId in workItemIds)
- {
- var workItem = workItemStore.GetWorkItem(workItemId);
- var workItemCheckinInfo = new WorkItemCheckinInfo(workItem, WorkItemCheckinAction.Associate);
- result.Add(workItemCheckinInfo);
- }
+ return workspace.QueryConflicts(targetPaths, true);
+ }
- return result.ToArray();
- }
+ private static void TryResolve(Workspace workspace, Conflict conflict, MergeOption mergeOption)
+ {
+ if (mergeOption == MergeOption.KeepTarget)
+ {
+ conflict.Resolution = Resolution.AcceptYours;
+ workspace.ResolveConflict(conflict);
+ }
+ if (mergeOption == MergeOption.OverwriteTarget)
+ {
+ conflict.Resolution = Resolution.AcceptTheirs;
+ workspace.ResolveConflict(conflict);
+ }
+ }
- private static bool CanCheckIn(CheckinEvaluationResult checkinEvaluationResult, bool skipPolicy)
- {
- var result = checkinEvaluationResult.Conflicts.IsNullOrEmpty()
- && checkinEvaluationResult.NoteFailures.IsNullOrEmpty()
- && checkinEvaluationResult.PolicyEvaluationException == null;
- if (!skipPolicy)
- result &= checkinEvaluationResult.PolicyFailures.IsNullOrEmpty();
- return result;
- }
+ private static WorkItemCheckinInfo[] GetWorkItemCheckinInfo(IReadOnlyCollection workItemIds, WorkItemStore workItemStore)
+ {
- private static void InvokeResolveConflictsPage(Workspace workspace, string[] targetPath)
- {
- var versionControlAssembly = Assembly.Load("Microsoft.VisualStudio.TeamFoundation.VersionControl");
- if (versionControlAssembly == null)
- return;
-
- var rcMgr = versionControlAssembly.GetType("Microsoft.VisualStudio.TeamFoundation.VersionControl.ResolveConflictsManager");
- if (rcMgr == null)
- return;
-
- const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
- var mi = rcMgr.GetMethod("Initialize", flags);
- var instantiatedType = Activator.CreateInstance(rcMgr, flags, null, null, null);
- mi.Invoke(instantiatedType, null);
-
- var resolveConflictsMethod = rcMgr.GetMethod("ResolveConflicts", BindingFlags.NonPublic | BindingFlags.Instance);
- resolveConflictsMethod.Invoke(instantiatedType,
- new object[] { workspace, targetPath, true, false });
- }
+ var result = new List(workItemIds.Count);
+ foreach (var workItemId in workItemIds)
+ {
+ var workItem = workItemStore.GetWorkItem(workItemId);
+ var workItemCheckinInfo = new WorkItemCheckinInfo(workItem, WorkItemCheckinAction.Associate);
+ result.Add(workItemCheckinInfo);
+ }
- private void SelectWorkspaceExecute(Workspace workspace)
- {
- Workspace = workspace;
- Refresh();
- }
+ return result.ToArray();
+ }
- private void SubscribeWorkspaceChanges(VersionControlServer versionControlServer)
- {
- versionControlServer.CreatedWorkspace += RefreshWorkspaces;
- versionControlServer.UpdatedWorkspace += RefreshWorkspaces;
- versionControlServer.DeletedWorkspace += RefreshWorkspaces;
- }
+ private static bool CanCheckIn(CheckinEvaluationResult checkinEvaluationResult, bool skipPolicy)
+ {
+ var result = checkinEvaluationResult.Conflicts.IsNullOrEmpty()
+ && checkinEvaluationResult.NoteFailures.IsNullOrEmpty()
+ && checkinEvaluationResult.PolicyEvaluationException == null;
- private void RefreshWorkspaces(object sender, WorkspaceEventArgs e)
- {
- var tfs = Context.TeamProjectCollection;
- var versionControl = tfs.GetService();
+ if (!skipPolicy)
+ result &= checkinEvaluationResult.PolicyFailures.IsNullOrEmpty();
+ return result;
+ }
- Workspaces = GetWorkspaces(versionControl, tfs);
- if (Workspaces.Count > 0)
- {
- Workspace = Workspaces[0];
- ShowWorkspaceChooser = Workspaces.Count > 1;
- }
- else
- {
- Workspace = null;
- }
- Refresh();
- }
+ private static void InvokeResolveConflictsPage(Workspace workspace, string[] targetPath)
+ {
+ var versionControlAssembly = Assembly.Load("Microsoft.VisualStudio.TeamFoundation.VersionControl");
+ if (versionControlAssembly == null)
+ return;
+
+ var rcMgr = versionControlAssembly.GetType("Microsoft.VisualStudio.TeamFoundation.VersionControl.ResolveConflictsManager");
+ if (rcMgr == null)
+ return;
+
+ const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
+ var mi = rcMgr.GetMethod("Initialize", flags);
+ var instantiatedType = Activator.CreateInstance(rcMgr, flags, null, null, null);
+ mi.Invoke(instantiatedType, null);
+
+ var resolveConflictsMethod = rcMgr.GetMethod("ResolveConflicts", BindingFlags.NonPublic | BindingFlags.Instance);
+ resolveConflictsMethod.Invoke(instantiatedType,
+ new object[] { workspace, targetPath, true, false });
+ }
- private void OpenSourceControlExplorerExecute()
- {
- // Using HACK.
- // Get any service which contain DTE object.
+ private void SelectWorkspaceExecute(Workspace workspace)
+ {
+ Workspace = workspace;
+ Refresh();
+ }
- var s = ServiceProvider.GetService() as SourceControl2;
- if (s != null)
- {
- dynamic ext = s.DTE.GetObject("Microsoft.VisualStudio.TeamFoundation.VersionControl.VersionControlExt");
- if (ext != null)
- {
- var explorer = ext.Explorer;
- if (explorer != null)
- {
- explorer.Navigate(SelectedBranch.TargetPath);
- }
- }
- }
- }
+ private void SubscribeWorkspaceChanges(VersionControlServer versionControlServer)
+ {
+ versionControlServer.CreatedWorkspace += RefreshWorkspaces;
+ versionControlServer.UpdatedWorkspace += RefreshWorkspaces;
+ versionControlServer.DeletedWorkspace += RefreshWorkspaces;
+ }
- private bool OpenSourceControlExplorerCanExecute()
- {
- return SelectedBranch != null && !string.IsNullOrEmpty(SelectedBranch.TargetPath);
- }
+ private void RefreshWorkspaces(object sender, WorkspaceEventArgs e)
+ {
+ var tfs = Context.TeamProjectCollection;
+ var versionControl = tfs.GetService();
+
+ Workspaces = GetWorkspaces(versionControl, tfs);
+ if (Workspaces.Count > 0)
+ {
+ Workspace = Workspaces[0];
+ ShowWorkspaceChooser = Workspaces.Count > 1;
+ }
+ else
+ {
+ Workspace = null;
+ }
+ Refresh();
+ }
- private void ViewChangesetDetailsExecute(int changesetId)
+ private void OpenSourceControlExplorerExecute()
+ {
+ // Using HACK.
+ // Get any service which contain DTE object.
+
+ var s = ServiceProvider.GetService() as SourceControl2;
+ if (s != null)
+ {
+ dynamic ext = s.DTE.GetObject("Microsoft.VisualStudio.TeamFoundation.VersionControl.VersionControlExt");
+ if (ext != null)
{
- TeamExplorerUtils.Instance.NavigateToPage(TeamExplorerPageIds.ChangesetDetails, ServiceProvider, changesetId);
+ var explorer = ext.Explorer;
+ if (explorer != null)
+ {
+ explorer.Navigate(SelectedBranch.TargetPath);
+ }
}
+ }
+ }
- public override void Dispose()
- {
- base.Dispose();
- if (_eventAggregator != null)
- {
- _eventAggregator.GetEvent().Unsubscribe(OnSelectedChangeset);
- _eventAggregator.GetEvent().Unsubscribe(OnBranchSelectedChanged);
- }
+ private bool OpenSourceControlExplorerCanExecute()
+ {
+ return SelectedBranch != null && !string.IsNullOrEmpty(SelectedBranch.TargetPath);
+ }
- var tfs = Context.TeamProjectCollection;
- if (tfs != null)
- {
- var versionControl = tfs.GetService();
- if (versionControl != null)
- {
- versionControl.CreatedWorkspace -= RefreshWorkspaces;
- versionControl.UpdatedWorkspace -= RefreshWorkspaces;
- versionControl.DeletedWorkspace -= RefreshWorkspaces;
- }
- }
- }
+ private void ViewChangesetDetailsExecute(int changesetId)
+ {
+ TeamExplorerUtils.Instance.NavigateToPage(TeamExplorerPageIds.ChangesetDetails, ServiceProvider, changesetId);
+ }
- public override void SaveContext(object sender, SectionSaveContextEventArgs e)
+ public override void Dispose()
+ {
+ base.Dispose();
+ if (_eventAggregator != null)
+ {
+ _eventAggregator.GetEvent().Unsubscribe(OnSelectedChangeset);
+ _eventAggregator.GetEvent().Unsubscribe(OnBranchSelectedChanged);
+ }
+
+ var tfs = Context.TeamProjectCollection;
+ if (tfs != null)
+ {
+ var versionControl = tfs.GetService();
+ if (versionControl != null)
{
- var context = new BranchesViewModelContext
- {
- Branches = Branches,
- Changeset = _changeset,
- ErrorMessage = ErrorMessage,
- MergeMode = MergeMode,
- MergeModes = MergeModes,
- MergeOption = MergeOption,
- SelectedBranch = SelectedBranch,
- ShowWorkspaceChooser = ShowWorkspaceChooser,
- Workspace = Workspace,
- Workspaces = Workspaces
- };
-
- e.Context = context;
+ versionControl.CreatedWorkspace -= RefreshWorkspaces;
+ versionControl.UpdatedWorkspace -= RefreshWorkspaces;
+ versionControl.DeletedWorkspace -= RefreshWorkspaces;
}
+ }
+ }
- private void RestoreContext(SectionInitializeEventArgs e)
- {
- var context = (BranchesViewModelContext)e.Context;
- _changeset = context.Changeset;
- Branches = context.Branches;
- ErrorMessage = context.ErrorMessage;
- MergeMode = context.MergeMode;
- MergeModes = context.MergeModes;
- MergeOption = context.MergeOption;
- SelectedBranch = context.SelectedBranch;
- ShowWorkspaceChooser = context.ShowWorkspaceChooser;
- Workspace = context.Workspace;
- Workspaces = context.Workspaces;
- }
+ public override void SaveContext(object sender, SectionSaveContextEventArgs e)
+ {
+ var context = new BranchesViewModelContext
+ {
+ Branches = Branches,
+ Changeset = _changeset,
+ ErrorMessage = ErrorMessage,
+ MergeMode = MergeMode,
+ MergeModes = MergeModes,
+ MergeOption = MergeOption,
+ SelectedBranch = SelectedBranch,
+ ShowWorkspaceChooser = ShowWorkspaceChooser,
+ Workspace = Workspace,
+ Workspaces = Workspaces
+ };
+
+ e.Context = context;
+ }
+
+ private void RestoreContext(SectionInitializeEventArgs e)
+ {
+ var context = (BranchesViewModelContext)e.Context;
+ _changeset = context.Changeset;
+ Branches = context.Branches;
+ ErrorMessage = context.ErrorMessage;
+ MergeMode = context.MergeMode;
+ MergeModes = context.MergeModes;
+ MergeOption = context.MergeOption;
+ SelectedBranch = context.SelectedBranch;
+ ShowWorkspaceChooser = context.ShowWorkspaceChooser;
+ Workspace = context.Workspace;
+ Workspaces = context.Workspaces;
}
+ }
}
diff --git a/src/AutoMerge/Commands/ShowAutoMergeWindow.cs b/src/AutoMerge/Commands/ShowAutoMergeWindow.cs
index b27aa06..132c0ac 100644
--- a/src/AutoMerge/Commands/ShowAutoMergeWindow.cs
+++ b/src/AutoMerge/Commands/ShowAutoMergeWindow.cs
@@ -1,7 +1,8 @@
+using System;
using System.ComponentModel.Design;
-using Microsoft.TeamFoundation.Common.Internal;
using Microsoft.TeamFoundation.Controls;
using Microsoft.VisualStudio.Shell;
+using Microsoft.TeamFoundation.Controls.WPF.TeamExplorer;
using Task = System.Threading.Tasks.Task;
namespace AutoMerge.Commands
@@ -24,8 +25,12 @@ private static void Execute(AsyncPackage package)
{
ThreadHelper.ThrowIfNotOnUIThread();
- var teamExplorer = package.GetService();
- teamExplorer.NavigateToPage(GuidList.AutoMergePageGuid, null);
+ // Navigate to the AutoMerge page in Team Explorer
+ var serviceProvider = package as IServiceProvider;
+ if (serviceProvider != null)
+ {
+ TeamExplorerUtils.Instance.NavigateToPage(GuidList.AutoMergePageGuid.ToString(), serviceProvider, null);
+ }
}
}
}
diff --git a/src/AutoMerge/Configuration/Settings.cs b/src/AutoMerge/Configuration/Settings.cs
index 3464497..a51d2a6 100644
--- a/src/AutoMerge/Configuration/Settings.cs
+++ b/src/AutoMerge/Configuration/Settings.cs
@@ -1,186 +1,187 @@
-using System;
+using System;
using System.Linq;
namespace AutoMerge
{
- internal class Settings
+ public class Settings
+ {
+ private readonly ISettingProvider _settingProvider;
+ private static readonly Lazy _instance;
+
+ private MergeMode? _lastMergeOperation;
+
+ private const string lastMergeOperationKey = "last_operation";
+ private const string mergeModeMerge = "merge";
+ private const string mergeModeMergeAndCheckin = "merge_checkin";
+
+ private const string mergeOperationDefaultKey = "merge_operation_default";
+ private const string mergeOperationDefaultLast = "last";
+ private const string mergeOperationDefaultMerge = mergeModeMerge;
+ private const string mergeOperationDefaultMergeCheckin = mergeModeMergeAndCheckin;
+ private readonly string[] _mergeOperationDefaultValues;
+
+ private const string commentFormatKey = "comment_format";
+ private const string commentFormatDefault = "MERGE {FromOriginalToTarget} ({OriginalComment})";
+ private const string commentFormatDiscardKey = "comment_format_discard";
+ private const string commentFormatDiscardDefault = "DISCARD {" + commentFormatKey + "}";
+ private const string branchDelimiterKey = "branch_delimiter";
+ private const string branchDelimiterDefault = " -> ";
+
+ private const string changesetCountKey = "changeset_count_show";
+ private const int changesetCountDefault = 20;
+
+ static Settings()
{
- private readonly ISettingProvider _settingProvider;
- private static readonly Lazy _instance;
-
- private MergeMode? _lastMergeOperation;
-
- private const string lastMergeOperationKey = "last_operation";
- private const string mergeModeMerge = "merge";
- private const string mergeModeMergeAndCheckin = "merge_checkin";
+ _instance = new Lazy(() => new Settings());
+ }
- private const string mergeOperationDefaultKey = "merge_operation_default";
- private const string mergeOperationDefaultLast = "last";
- private const string mergeOperationDefaultMerge = mergeModeMerge;
- private const string mergeOperationDefaultMergeCheckin = mergeModeMergeAndCheckin;
- private readonly string[] _mergeOperationDefaultValues;
+ private Settings()
+ {
+ _settingProvider = new FileSettingProvider();
+ _mergeOperationDefaultValues = new[]
+ {mergeOperationDefaultLast, mergeOperationDefaultMerge, mergeOperationDefaultMergeCheckin};
+ }
- private const string commentFormatKey = "comment_format";
- private const string commentFormatDefault = "MERGE {FromOriginalToTarget} ({OriginalComment})";
- private const string commentFormatDiscardKey = "comment_format_discard";
- private const string commentFormatDiscardDefault = "DISCARD {" + commentFormatKey + "}";
- private const string branchDelimiterKey = "branch_delimiter";
- private const string branchDelimiterDefault = " -> ";
+ public static Settings Instance
+ {
+ get { return _instance.Value; }
+ }
- private const string changesetCountKey = "changeset_count_show";
- private const int changesetCountDefault = 20;
+ public MergeMode LastMergeOperation
+ {
+ get
+ {
+ return LastMergeOperationGet();
+ }
+ set
+ {
+ LastMergeOperationSet(value);
+ }
+ }
- static Settings()
- {
- _instance = new Lazy(() => new Settings());
- }
+ public CommentFormat CommentFormat
+ {
+ get { return CommentFormatGet(); }
+ }
- private Settings()
- {
- _settingProvider = new FileSettingProvider();
- _mergeOperationDefaultValues = new[]
- {mergeOperationDefaultLast, mergeOperationDefaultMerge, mergeOperationDefaultMergeCheckin};
- }
+ public int ChangesetCount
+ {
+ get { return ChangesetCountGet(); }
+ }
- public static Settings Instance
- {
- get { return _instance.Value; }
- }
+ private CommentFormat CommentFormatGet()
+ {
+ string commentFormat;
+ if (!_settingProvider.TryReadValue(commentFormatKey, out commentFormat))
+ {
+ commentFormat = commentFormatDefault;
+ }
+
+ string commentFormatDiscard;
+ if (!_settingProvider.TryReadValue(commentFormatDiscardKey, out commentFormatDiscard))
+ {
+ commentFormatDiscard = commentFormatDiscardDefault;
+ }
+
+ commentFormatDiscard = commentFormatDiscard.Replace("{" + commentFormatKey + "}", commentFormat);
+
+ string branchDelimiter;
+ if (!_settingProvider.TryReadValue(branchDelimiterKey, out branchDelimiter))
+ {
+ branchDelimiter = branchDelimiterDefault;
+ }
+
+ return new CommentFormat
+ {
+ Format = commentFormat,
+ BranchDelimiter = branchDelimiter,
+ DiscardFormat = commentFormatDiscard
+ };
- public MergeMode LastMergeOperation {
- get
- {
- return LastMergeOperationGet();
- }
- set
- {
- LastMergeOperationSet(value);
- }
- }
+ }
- public CommentFormat CommentFormat
+ private MergeMode LastMergeOperationGet()
+ {
+ MergeMode result;
+ var mergeOperationDefaultValue = MergeOperationDefaultGet();
+ if (mergeOperationDefaultValue == mergeOperationDefaultLast)
+ {
+ if (!_lastMergeOperation.HasValue)
{
- get { return CommentFormatGet(); }
- }
+ string stringValue;
+ if (!_settingProvider.TryReadValue(lastMergeOperationKey, out stringValue))
+ {
+ stringValue = mergeModeMergeAndCheckin;
+ }
- public int ChangesetCount
- {
- get { return ChangesetCountGet(); }
+ _lastMergeOperation = ToMergeMode(stringValue);
}
- private CommentFormat CommentFormatGet()
- {
- string commentFormat;
- if (!_settingProvider.TryReadValue(commentFormatKey, out commentFormat))
- {
- commentFormat = commentFormatDefault;
- }
-
- string commentFormatDiscard;
- if (!_settingProvider.TryReadValue(commentFormatDiscardKey, out commentFormatDiscard))
- {
- commentFormatDiscard = commentFormatDiscardDefault;
- }
-
- commentFormatDiscard = commentFormatDiscard.Replace("{" + commentFormatKey + "}", commentFormat);
-
- string branchDelimiter;
- if (!_settingProvider.TryReadValue(branchDelimiterKey, out branchDelimiter))
- {
- branchDelimiter = branchDelimiterDefault;
- }
-
- return new CommentFormat
- {
- Format = commentFormat,
- BranchDelimiter = branchDelimiter,
- DiscardFormat = commentFormatDiscard
- };
+ result = _lastMergeOperation.Value;
+ }
+ else
+ {
+ result = ToMergeMode(mergeOperationDefaultValue);
+ }
- }
+ return result;
+ }
- private MergeMode LastMergeOperationGet()
- {
- MergeMode result;
- var mergeOperationDefaultValue = MergeOperationDefaultGet();
- if (mergeOperationDefaultValue == mergeOperationDefaultLast)
- {
- if (!_lastMergeOperation.HasValue)
- {
- string stringValue;
- if (!_settingProvider.TryReadValue(lastMergeOperationKey, out stringValue))
- {
- stringValue = mergeModeMergeAndCheckin;
- }
-
- _lastMergeOperation = ToMergeMode(stringValue);
- }
-
- result = _lastMergeOperation.Value;
- }
- else
- {
- result = ToMergeMode(mergeOperationDefaultValue);
- }
-
- return result;
- }
+ private void LastMergeOperationSet(MergeMode mergeMode)
+ {
+ if (_lastMergeOperation != mergeMode)
+ {
+ var stringValue = ToString(mergeMode);
+ _settingProvider.WriteValue(lastMergeOperationKey, stringValue);
+ _lastMergeOperation = mergeMode;
+ }
+ }
- private void LastMergeOperationSet(MergeMode mergeMode)
- {
- if (_lastMergeOperation != mergeMode)
- {
- var stringValue = ToString(mergeMode);
- _settingProvider.WriteValue(lastMergeOperationKey, stringValue);
- _lastMergeOperation = mergeMode;
- }
- }
+ private static MergeMode ToMergeMode(string stringValue)
+ {
+ if (stringValue == mergeModeMergeAndCheckin)
+ return MergeMode.MergeAndCheckIn;
+ return MergeMode.Merge;
+ }
- private static MergeMode ToMergeMode(string stringValue)
- {
- if (stringValue == mergeModeMergeAndCheckin)
- return MergeMode.MergeAndCheckIn;
- return MergeMode.Merge;
- }
+ private static string ToString(MergeMode mergeMode)
+ {
+ switch (mergeMode)
+ {
+ case MergeMode.Merge:
+ return mergeModeMerge;
+ case MergeMode.MergeAndCheckIn:
+ return mergeModeMergeAndCheckin;
+ default:
+ return "unknown";
+ }
+ }
- private static string ToString(MergeMode mergeMode)
- {
- switch (mergeMode)
- {
- case MergeMode.Merge:
- return mergeModeMerge;
- case MergeMode.MergeAndCheckIn:
- return mergeModeMergeAndCheckin;
- default:
- return "unknown";
- }
- }
+ private string MergeOperationDefaultGet()
+ {
+ string mergeOperationDefaultValue;
+ if (!_settingProvider.TryReadValue(mergeOperationDefaultKey, out mergeOperationDefaultValue))
+ {
+ mergeOperationDefaultValue = mergeOperationDefaultLast;
+ _settingProvider.WriteValue(mergeOperationDefaultKey, mergeOperationDefaultValue);
+ }
- private string MergeOperationDefaultGet()
- {
- string mergeOperationDefaultValue;
- if (!_settingProvider.TryReadValue(mergeOperationDefaultKey, out mergeOperationDefaultValue))
- {
- mergeOperationDefaultValue = mergeOperationDefaultLast;
- _settingProvider.WriteValue(mergeOperationDefaultKey, mergeOperationDefaultValue);
- }
+ if (!_mergeOperationDefaultValues.Contains(mergeOperationDefaultValue))
+ mergeOperationDefaultValue = "mergeOperationDefaultLast";
- if (!_mergeOperationDefaultValues.Contains(mergeOperationDefaultValue))
- mergeOperationDefaultValue = "mergeOperationDefaultLast";
+ return mergeOperationDefaultValue;
+ }
- return mergeOperationDefaultValue;
- }
+ private int ChangesetCountGet()
+ {
+ int changesetCount;
- private int ChangesetCountGet()
- {
- int changesetCount;
- if (!_settingProvider.TryReadValue(changesetCountKey, out changesetCount))
- {
- changesetCount = changesetCountDefault;
- }
+ if (!_settingProvider.TryReadValue(changesetCountKey, out changesetCount))
+ {
+ changesetCount = changesetCountDefault;
+ }
- return changesetCount;
- }
+ return changesetCount;
}
+ }
}
-
diff --git a/src/AutoMerge/RecentChangesets/ChangesetByIdChangesetProvider.cs b/src/AutoMerge/RecentChangesets/ChangesetByIdChangesetProvider.cs
index e8d65f2..27e3a1e 100644
--- a/src/AutoMerge/RecentChangesets/ChangesetByIdChangesetProvider.cs
+++ b/src/AutoMerge/RecentChangesets/ChangesetByIdChangesetProvider.cs
@@ -17,6 +17,15 @@ public ChangesetByIdChangesetProvider(IServiceProvider serviceProvider, IEnumera
_changesetIds = changesetIds;
}
+ public ChangesetByIdChangesetProvider(ChangesetService changesetService, IEnumerable changesetIds)
+ : base(changesetService, null)
+ {
+ if (changesetIds == null)
+ throw new ArgumentNullException("changesetIds");
+
+ _changesetIds = changesetIds;
+ }
+
protected override List GetChangesetsInternal(string userLogin)
{
var changesets = new List();
@@ -33,4 +42,4 @@ protected override List GetChangesetsInternal(string userLog
return changesets;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/AutoMerge/RecentChangesets/ChangesetProviderBase.cs b/src/AutoMerge/RecentChangesets/ChangesetProviderBase.cs
index 17627e5..ef88773 100644
--- a/src/AutoMerge/RecentChangesets/ChangesetProviderBase.cs
+++ b/src/AutoMerge/RecentChangesets/ChangesetProviderBase.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
@@ -6,65 +6,89 @@
namespace AutoMerge
{
- public abstract class ChangesetProviderBase : IChangesetProvider
+ public abstract class ChangesetProviderBase : IChangesetProvider
+ {
+ private readonly IServiceProvider _serviceProvider;
+ private readonly Lazy _changesetService;
+ private readonly ChangesetService _overriddenChangesetService;
+ private readonly string _projectName;
+
+ protected ChangesetProviderBase(IServiceProvider serviceProvider)
{
- private readonly IServiceProvider _serviceProvider;
- private readonly Lazy _changesetService;
+ _serviceProvider = serviceProvider;
+ _changesetService = new Lazy(InitChangesetService);
+ }
- protected ChangesetProviderBase(IServiceProvider serviceProvider)
- {
- _serviceProvider = serviceProvider;
- _changesetService = new Lazy(InitChangesetService);
- }
+ protected ChangesetProviderBase(ChangesetService changesetService, string projectName)
+ {
+ _overriddenChangesetService = changesetService;
+ _projectName = projectName;
+ _changesetService = new Lazy(() => changesetService);
+ }
- public Task> GetChangesets(string userLogin)
- {
- return Task.Run(() => GetChangesetsInternal(userLogin));
- }
+ public Task> GetChangesets(string userLogin)
+ {
+ return Task.Run(() => GetChangesetsInternal(userLogin));
+ }
- protected abstract List GetChangesetsInternal(string userLogin);
+ protected abstract List GetChangesetsInternal(string userLogin);
- protected ChangesetViewModel ToChangesetViewModel(Changeset tfsChangeset, ChangesetService changesetService)
- {
- var changesetViewModel = new ChangesetViewModel
- {
- ChangesetId = tfsChangeset.ChangesetId,
- Comment = tfsChangeset.Comment,
- Branches = changesetService.GetAssociatedBranches(tfsChangeset.ChangesetId)
- .Select(i => i.Item)
- .ToList()
- };
-
- return changesetViewModel;
- }
+ protected ChangesetViewModel ToChangesetViewModel(Changeset tfsChangeset, ChangesetService changesetService)
+ {
+ var changesetViewModel = new ChangesetViewModel
+ {
+ ChangesetId = tfsChangeset.ChangesetId,
+ Comment = tfsChangeset.Comment,
+ Branches = changesetService.GetAssociatedBranches(tfsChangeset.ChangesetId)
+ .Select(i => i.Item)
+ .ToList()
+ };
- protected ChangesetService GetChangesetService()
- {
- return _changesetService.Value;
- }
+ return changesetViewModel;
+ }
- private ChangesetService InitChangesetService()
- {
- var context = VersionControlNavigationHelper.GetTeamFoundationContext(_serviceProvider);
- if (context != null && VersionControlNavigationHelper.IsConnectedToTfsCollectionAndProject(context))
- {
- var vcs = context.TeamProjectCollection.GetService();
- if (vcs != null)
- {
- return new ChangesetService(vcs);
- }
- }
- return null;
- }
+ protected ChangesetService GetChangesetService()
+ {
+ if (_overriddenChangesetService != null)
+ {
+ return _overriddenChangesetService;
+ }
+
+ return _changesetService.Value;
+ }
+
+ private ChangesetService InitChangesetService()
+ {
+ var context = VersionControlNavigationHelper.GetTeamFoundationContext(_serviceProvider);
+
+ if (context != null && VersionControlNavigationHelper.IsConnectedToTfsCollectionAndProject(context))
+ {
+ var vcs = context.TeamProjectCollection.GetService();
- protected string GetProjectName()
+ if (vcs != null)
{
- var context = VersionControlNavigationHelper.GetTeamFoundationContext(_serviceProvider);
- if (context != null)
- {
- return context.TeamProjectName;
- }
- return null;
+ return new ChangesetService(vcs);
}
+ }
+
+ return null;
+ }
+
+ protected string GetProjectName()
+ {
+ if (!string.IsNullOrWhiteSpace(_projectName))
+ {
+ return _projectName;
+ }
+
+ var context = VersionControlNavigationHelper.GetTeamFoundationContext(_serviceProvider);
+
+ if (context != null)
+ {
+ return context.TeamProjectName;
+ }
+
+ return null;
}
+ }
}
diff --git a/src/AutoMerge/RecentChangesets/MyChangesetChangesetProvider.cs b/src/AutoMerge/RecentChangesets/MyChangesetChangesetProvider.cs
index 733d923..f9beb71 100644
--- a/src/AutoMerge/RecentChangesets/MyChangesetChangesetProvider.cs
+++ b/src/AutoMerge/RecentChangesets/MyChangesetChangesetProvider.cs
@@ -1,38 +1,67 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
namespace AutoMerge
{
- public class MyChangesetChangesetProvider : ChangesetProviderBase
- {
- private readonly int _maxChangesetCount;
-
- public MyChangesetChangesetProvider(IServiceProvider serviceProvider, int maxChangesetCount)
- : base(serviceProvider)
- {
- _maxChangesetCount = maxChangesetCount;
- }
-
- protected override List GetChangesetsInternal(string userLogin)
- {
- var changesets = new List();
-
- if (!string.IsNullOrEmpty(userLogin))
- {
- var changesetService = GetChangesetService();
-
- if (changesetService != null)
- {
- var projectName = GetProjectName();
- var tfsChangesets = changesetService.GetUserChangesets(projectName, userLogin, _maxChangesetCount);
- changesets = tfsChangesets
- .Select(tfsChangeset => ToChangesetViewModel(tfsChangeset, changesetService))
- .ToList();
- }
- }
-
- return changesets;
- }
- }
+ public class MyChangesetChangesetProvider : ChangesetProviderBase
+ {
+ private readonly int _maxChangesetCount;
+
+ private readonly bool _filterOutMergeChangesets;
+
+ public MyChangesetChangesetProvider(IServiceProvider serviceProvider, int maxChangesetCount)
+ : base(serviceProvider)
+ {
+ _maxChangesetCount = maxChangesetCount;
+ }
+
+ public MyChangesetChangesetProvider(ChangesetService changesetService, string teamProjectName, int maxChangesetCount)
+ : base(changesetService, teamProjectName)
+ {
+ _maxChangesetCount = maxChangesetCount;
+ }
+
+ public MyChangesetChangesetProvider(ChangesetService changesetService, string teamProjectName, int maxChangesetCount, bool filterOutMergeChangesets)
+ : this(changesetService, teamProjectName, maxChangesetCount)
+ {
+ _filterOutMergeChangesets = filterOutMergeChangesets;
+ }
+
+ protected override List GetChangesetsInternal(string userLogin)
+ {
+ var changesets = new List();
+
+ if (!string.IsNullOrEmpty(userLogin))
+ {
+ var changesetService = GetChangesetService();
+
+ if (changesetService != null)
+ {
+ var projectName = GetProjectName();
+
+ if (_filterOutMergeChangesets)
+ {
+ var tfsChangesets = changesetService.GetUserChangesets(projectName, userLogin, _maxChangesetCount * 2);
+
+ changesets = tfsChangesets
+ .Select(tfsChangeset => ToChangesetViewModel(tfsChangeset, changesetService))
+ .Where(cs => !cs.Comment.StartsWith("MERGE") && cs.Branches.Count == 1)
+ .Take(_maxChangesetCount)
+ .ToList();
+ }
+ else
+ {
+ var tfsChangesets = changesetService.GetUserChangesets(projectName, userLogin, _maxChangesetCount);
+
+ changesets = tfsChangesets
+ .Select(tfsChangeset => ToChangesetViewModel(tfsChangeset, changesetService))
+ .ToList();
+ }
+ }
+ }
+
+ return changesets;
+ }
+ }
}
diff --git a/src/AutoMerge/RecentChangesets/RecentChangesetsViewModel.cs b/src/AutoMerge/RecentChangesets/RecentChangesetsViewModel.cs
index c5c5567..3c0387a 100644
--- a/src/AutoMerge/RecentChangesets/RecentChangesetsViewModel.cs
+++ b/src/AutoMerge/RecentChangesets/RecentChangesetsViewModel.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using AutoMerge.Events;
@@ -14,294 +14,295 @@
namespace AutoMerge
{
- public sealed class RecentChangesetsViewModel : TeamExplorerSectionViewModelBase
+ public sealed class RecentChangesetsViewModel : TeamExplorerSectionViewModelBase
+ {
+ private readonly string _baseTitle;
+ private readonly IEventAggregator _eventAggregator;
+
+ public RecentChangesetsViewModel(ILogger logger)
+ : base(logger)
{
- private readonly string _baseTitle;
- private readonly IEventAggregator _eventAggregator;
+ Title = Resources.RecentChangesetSectionName;
+ IsVisible = true;
+ IsExpanded = true;
+ IsBusy = false;
+ Changesets = new ObservableCollection();
+ _baseTitle = Title;
+
+ _eventAggregator = EventAggregatorFactory.Get();
+ _eventAggregator.GetEvent()
+ .Subscribe(OnMergeComplete);
+
+ ViewChangesetDetailsCommand = new DelegateCommand(ViewChangesetDetailsExecute, ViewChangesetDetailsCanExecute);
+ ToggleAddByIdCommand = new DelegateCommand(ToggleAddByIdExecute, ToggleAddByIdCanExecute);
+ CancelAddChangesetByIdCommand = new DelegateCommand(CancelAddByIdExecute);
+ AddChangesetByIdCommand = new DelegateCommand(AddChangesetByIdExecute, AddChangesetByIdCanExecute);
+ }
- public RecentChangesetsViewModel(ILogger logger)
- : base(logger)
- {
- Title = Resources.RecentChangesetSectionName;
- IsVisible = true;
- IsExpanded = true;
- IsBusy = false;
- Changesets = new ObservableCollection();
- _baseTitle = Title;
-
- _eventAggregator = EventAggregatorFactory.Get();
- _eventAggregator.GetEvent()
- .Subscribe(OnMergeComplete);
-
- ViewChangesetDetailsCommand = new DelegateCommand(ViewChangesetDetailsExecute, ViewChangesetDetailsCanExecute);
- ToggleAddByIdCommand = new DelegateCommand(ToggleAddByIdExecute, ToggleAddByIdCanExecute);
- CancelAddChangesetByIdCommand = new DelegateCommand(CancelAddByIdExecute);
- AddChangesetByIdCommand = new DelegateCommand(AddChangesetByIdExecute, AddChangesetByIdCanExecute);
- }
+ public ChangesetViewModel SelectedChangeset
+ {
+ get
+ {
+ return _selectedChangeset;
+ }
+ set
+ {
+ _selectedChangeset = value;
+ RaisePropertyChanged("SelectedChangeset");
+ _eventAggregator.GetEvent().Publish(value);
+ }
+ }
+ private ChangesetViewModel _selectedChangeset;
- public ChangesetViewModel SelectedChangeset
- {
- get
- {
- return _selectedChangeset;
- }
- set
- {
- _selectedChangeset = value;
- RaisePropertyChanged("SelectedChangeset");
- _eventAggregator.GetEvent().Publish(value);
- }
- }
- private ChangesetViewModel _selectedChangeset;
+ public ObservableCollection Changesets
+ {
+ get
+ {
+ return _changesets;
+ }
+ private set
+ {
+ _changesets = value;
+ RaisePropertyChanged("Changesets");
+ }
+ }
+ private ObservableCollection _changesets;
- public ObservableCollection Changesets
- {
- get
- {
- return _changesets;
- }
- private set
- {
- _changesets = value;
- RaisePropertyChanged("Changesets");
- }
- }
- private ObservableCollection _changesets;
+ public bool ShowAddByIdChangeset
+ {
+ get
+ {
+ return _showAddByIdChangeset;
+ }
+ set
+ {
+ _showAddByIdChangeset = value;
+ RaisePropertyChanged("ShowAddByIdChangeset");
+ }
+ }
+ private bool _showAddByIdChangeset;
- public bool ShowAddByIdChangeset
- {
- get
- {
- return _showAddByIdChangeset;
- }
- set
- {
- _showAddByIdChangeset = value;
- RaisePropertyChanged("ShowAddByIdChangeset");
- }
- }
- private bool _showAddByIdChangeset;
+ public string ChangesetIdsText
+ {
+ get
+ {
+ return _changesetIdsText;
+ }
+ set
+ {
+ _changesetIdsText = value;
+ RaisePropertyChanged("ChangesetIdsText");
+ InvalidateCommands();
+ }
+ }
+ private string _changesetIdsText;
- public string ChangesetIdsText
- {
- get
- {
- return _changesetIdsText;
- }
- set
- {
- _changesetIdsText = value;
- RaisePropertyChanged("ChangesetIdsText");
- InvalidateCommands();
- }
- }
- private string _changesetIdsText;
+ public DelegateCommand ViewChangesetDetailsCommand { get; private set; }
- public DelegateCommand ViewChangesetDetailsCommand { get; private set; }
+ public DelegateCommand ToggleAddByIdCommand { get; private set; }
- public DelegateCommand ToggleAddByIdCommand { get; private set; }
+ public DelegateCommand AddChangesetByIdCommand { get; private set; }
- public DelegateCommand AddChangesetByIdCommand { get; private set; }
+ public DelegateCommand CancelAddChangesetByIdCommand { get; private set; }
- public DelegateCommand CancelAddChangesetByIdCommand { get; private set; }
+ private void ViewChangesetDetailsExecute()
+ {
+ var changesetId = SelectedChangeset.ChangesetId;
+ TeamExplorerUtils.Instance.NavigateToPage(TeamExplorerPageIds.ChangesetDetails, ServiceProvider, changesetId);
+ }
- private void ViewChangesetDetailsExecute()
- {
- var changesetId = SelectedChangeset.ChangesetId;
- TeamExplorerUtils.Instance.NavigateToPage(TeamExplorerPageIds.ChangesetDetails, ServiceProvider, changesetId);
- }
+ private bool ViewChangesetDetailsCanExecute()
+ {
+ return SelectedChangeset != null;
+ }
- private bool ViewChangesetDetailsCanExecute()
- {
- return SelectedChangeset != null;
- }
+ private async void OnMergeComplete(bool obj)
+ {
+ await RefreshAsync();
+ }
- private async void OnMergeComplete(bool obj)
- {
- await RefreshAsync();
- }
+ protected override async Task InitializeAsync(object sender, SectionInitializeEventArgs e)
+ {
+ if (e.Context == null)
+ {
+ await RefreshAsync();
+ }
+ else
+ {
+ RestoreContext(e);
+ }
+ }
- protected override async Task InitializeAsync(object sender, SectionInitializeEventArgs e)
- {
- if (e.Context == null)
- {
- await RefreshAsync();
- }
- else
- {
- RestoreContext(e);
- }
- }
+ protected override async Task RefreshAsync()
+ {
+ Changesets.Clear();
- protected override async Task RefreshAsync()
- {
- Changesets.Clear();
+ var changesetProvider = new MyChangesetChangesetProvider(ServiceProvider, Settings.Instance.ChangesetCount);
- var changesetProvider = new MyChangesetChangesetProvider(ServiceProvider, Settings.Instance.ChangesetCount);
- var userLogin = VersionControlNavigationHelper.GetAuthorizedUser(ServiceProvider);
+ var userLogin = VersionControlNavigationHelper.GetAuthorizedUser(ServiceProvider);
- Logger.Info("Getting changesets ...");
- var changesets = await changesetProvider.GetChangesets(userLogin);
- Logger.Info("Getting changesets end");
+ Logger.Info("Getting changesets ...");
+ var changesets = await changesetProvider.GetChangesets(userLogin);
+ Logger.Info("Getting changesets end");
- Changesets = new ObservableCollection(changesets);
- UpdateTitle();
+ Changesets = new ObservableCollection(changesets);
+ UpdateTitle();
- if (Changesets.Count > 0)
- {
- if (SelectedChangeset == null || SelectedChangeset.ChangesetId != Changesets[0].ChangesetId)
- SelectedChangeset = Changesets[0];
- }
- }
+ if (Changesets.Count > 0)
+ {
+ if (SelectedChangeset == null || SelectedChangeset.ChangesetId != Changesets[0].ChangesetId)
+ SelectedChangeset = Changesets[0];
+ }
+ }
- private void UpdateTitle()
- {
- Title = Changesets.Count > 0
- ? string.Format("{0} ({1})", _baseTitle, Changesets.Count)
- : _baseTitle;
- }
+ private void UpdateTitle()
+ {
+ Title = Changesets.Count > 0
+ ? string.Format("{0} ({1})", _baseTitle, Changesets.Count)
+ : _baseTitle;
+ }
- private void ToggleAddByIdExecute()
- {
- try
- {
- ShowAddByIdChangeset = true;
- InvalidateCommands();
- ResetAddById();
- SetMvvmFocus(RecentChangesetFocusableControlNames.ChangesetIdTextBox);
- }
- catch (Exception ex)
- {
- ShowException(ex);
- throw;
- }
- }
+ private void ToggleAddByIdExecute()
+ {
+ try
+ {
+ ShowAddByIdChangeset = true;
+ InvalidateCommands();
+ ResetAddById();
+ SetMvvmFocus(RecentChangesetFocusableControlNames.ChangesetIdTextBox);
+ }
+ catch (Exception ex)
+ {
+ ShowException(ex);
+ throw;
+ }
+ }
- private bool ToggleAddByIdCanExecute()
- {
- return !ShowAddByIdChangeset;
- }
+ private bool ToggleAddByIdCanExecute()
+ {
+ return !ShowAddByIdChangeset;
+ }
- private void CancelAddByIdExecute()
- {
- try
- {
- ShowAddByIdChangeset = false;
- InvalidateCommands();
- SetMvvmFocus(RecentChangesetFocusableControlNames.AddChangesetByIdLink);
- ResetAddById();
- }
- catch (Exception ex)
- {
- ShowException(ex);
- }
- }
+ private void CancelAddByIdExecute()
+ {
+ try
+ {
+ ShowAddByIdChangeset = false;
+ InvalidateCommands();
+ SetMvvmFocus(RecentChangesetFocusableControlNames.AddChangesetByIdLink);
+ ResetAddById();
+ }
+ catch (Exception ex)
+ {
+ ShowException(ex);
+ }
+ }
- private void ResetAddById()
- {
- ChangesetIdsText = string.Empty;
- }
+ private void ResetAddById()
+ {
+ ChangesetIdsText = string.Empty;
+ }
- private async void AddChangesetByIdExecute()
+ private async void AddChangesetByIdExecute()
+ {
+ ShowBusy();
+ try
+ {
+ var changesetIds = GeChangesetIdsToAdd(ChangesetIdsText);
+ if (changesetIds.Count > 0)
{
- ShowBusy();
- try
- {
- var changesetIds = GeChangesetIdsToAdd(ChangesetIdsText);
- if (changesetIds.Count > 0)
- {
- var changesetProvider = new ChangesetByIdChangesetProvider(ServiceProvider, changesetIds);
- var changesets = await changesetProvider.GetChangesets(null);
-
- if (changesets.Count > 0)
- {
- Changesets.Add(changesets[0]);
- SelectedChangeset = changesets[0];
- SetMvvmFocus(RecentChangesetFocusableControlNames.ChangesetList);
- UpdateTitle();
- }
- ShowAddByIdChangeset = false;
- }
- }
- catch (Exception ex)
- {
- ShowException(ex);
- }
- HideBusy();
+ var changesetProvider = new ChangesetByIdChangesetProvider(ServiceProvider, changesetIds);
+ var changesets = await changesetProvider.GetChangesets(null);
+
+ if (changesets.Count > 0)
+ {
+ Changesets.Add(changesets[0]);
+ SelectedChangeset = changesets[0];
+ SetMvvmFocus(RecentChangesetFocusableControlNames.ChangesetList);
+ UpdateTitle();
+ }
+ ShowAddByIdChangeset = false;
}
+ }
+ catch (Exception ex)
+ {
+ ShowException(ex);
+ }
+ HideBusy();
+ }
- private bool AddChangesetByIdCanExecute()
- {
- try
- {
- return GeChangesetIdsToAdd(ChangesetIdsText).Count > 0;
- }
- catch (Exception ex)
- {
- ShowException(ex);
- TeamFoundationTrace.TraceException(ex);
- }
- return false;
- }
+ private bool AddChangesetByIdCanExecute()
+ {
+ try
+ {
+ return GeChangesetIdsToAdd(ChangesetIdsText).Count > 0;
+ }
+ catch (Exception ex)
+ {
+ ShowException(ex);
+ TeamFoundationTrace.TraceException(ex);
+ }
+ return false;
+ }
- private static List GeChangesetIdsToAdd(string text)
+ private static List GeChangesetIdsToAdd(string text)
+ {
+ var list = new List();
+ var idsStrArray = string.IsNullOrEmpty(text) ? new string[0] : text.Split(new[] { ',', ';' });
+ if (idsStrArray.Length > 0)
+ {
+ foreach (var idStr in idsStrArray)
{
- var list = new List();
- var idsStrArray = string.IsNullOrEmpty(text) ? new string[0] : text.Split(new[] { ',', ';' });
- if (idsStrArray.Length > 0)
- {
- foreach (var idStr in idsStrArray)
- {
- int result;
- if (int.TryParse(idStr.Trim(), out result) && result > 0)
- list.Add(result);
- }
- }
- return list;
+ int result;
+ if (int.TryParse(idStr.Trim(), out result) && result > 0)
+ list.Add(result);
}
+ }
+ return list;
+ }
- private void InvalidateCommands()
- {
- ViewChangesetDetailsCommand.RaiseCanExecuteChanged();
- ToggleAddByIdCommand.RaiseCanExecuteChanged();
- CancelAddChangesetByIdCommand.RaiseCanExecuteChanged();
- AddChangesetByIdCommand.RaiseCanExecuteChanged();
- }
+ private void InvalidateCommands()
+ {
+ ViewChangesetDetailsCommand.RaiseCanExecuteChanged();
+ ToggleAddByIdCommand.RaiseCanExecuteChanged();
+ CancelAddChangesetByIdCommand.RaiseCanExecuteChanged();
+ AddChangesetByIdCommand.RaiseCanExecuteChanged();
+ }
- public override void Dispose()
- {
- base.Dispose();
- _eventAggregator.GetEvent().Unsubscribe(OnMergeComplete);
- }
+ public override void Dispose()
+ {
+ base.Dispose();
+ _eventAggregator.GetEvent().Unsubscribe(OnMergeComplete);
+ }
- public override void SaveContext(object sender, SectionSaveContextEventArgs e)
- {
- base.SaveContext(sender, e);
- var context = new RecentChangesetsViewModelContext
- {
- ChangesetIdsText = ChangesetIdsText,
- Changesets = Changesets,
- SelectedChangeset = SelectedChangeset,
- ShowAddByIdChangeset = ShowAddByIdChangeset,
- Title = Title
- };
-
- e.Context = context;
- }
+ public override void SaveContext(object sender, SectionSaveContextEventArgs e)
+ {
+ base.SaveContext(sender, e);
+ var context = new RecentChangesetsViewModelContext
+ {
+ ChangesetIdsText = ChangesetIdsText,
+ Changesets = Changesets,
+ SelectedChangeset = SelectedChangeset,
+ ShowAddByIdChangeset = ShowAddByIdChangeset,
+ Title = Title
+ };
+
+ e.Context = context;
+ }
- private void RestoreContext(SectionInitializeEventArgs e)
- {
- var context = (RecentChangesetsViewModelContext)e.Context;
- ChangesetIdsText = context.ChangesetIdsText;
- Changesets = context.Changesets;
- SelectedChangeset = context.SelectedChangeset;
- ShowAddByIdChangeset = context.ShowAddByIdChangeset;
- Title = context.Title;
- }
+ private void RestoreContext(SectionInitializeEventArgs e)
+ {
+ var context = (RecentChangesetsViewModelContext)e.Context;
+ ChangesetIdsText = context.ChangesetIdsText;
+ Changesets = context.Changesets;
+ SelectedChangeset = context.SelectedChangeset;
+ ShowAddByIdChangeset = context.ShowAddByIdChangeset;
+ Title = context.Title;
+ }
- protected override void OnContextChanged(object sender, ContextChangedEventArgs e)
- {
- Refresh();
- }
+ protected override void OnContextChanged(object sender, ContextChangedEventArgs e)
+ {
+ Refresh();
}
+ }
}
diff --git a/src/AutoMerge/Resources.Designer.cs b/src/AutoMerge/Resources.Designer.cs
index 9033603..7635965 100644
--- a/src/AutoMerge/Resources.Designer.cs
+++ b/src/AutoMerge/Resources.Designer.cs
@@ -19,10 +19,10 @@ namespace AutoMerge {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "18.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- internal class Resources {
+ public class Resources {
private static global::System.Resources.ResourceManager resourceMan;
@@ -36,7 +36,7 @@ internal Resources() {
/// Returns the cached ResourceManager instance used by this class.
///
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Resources.ResourceManager ResourceManager {
+ public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoMerge.Resources", typeof(Resources).Assembly);
@@ -51,7 +51,7 @@ internal Resources() {
/// resource lookups using this strongly typed resource class.
///
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Globalization.CultureInfo Culture {
+ public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
@@ -61,9 +61,9 @@ internal Resources() {
}
///
- /// Looks up a localized string similar to Intact Auto Merge.
+ /// Looks up a localized string similar to GenetiQ Auto Merge.
///
- internal static string AutoMergePageName {
+ public static string AutoMergePageName {
get {
return ResourceManager.GetString("AutoMergePageName", resourceCulture);
}
@@ -72,7 +72,7 @@ internal static string AutoMergePageName {
///
/// Looks up a localized string similar to Target branches.
///
- internal static string BrancheSectionName {
+ public static string BrancheSectionName {
get {
return ResourceManager.GetString("BrancheSectionName", resourceCulture);
}
@@ -81,7 +81,7 @@ internal static string BrancheSectionName {
///
/// Looks up a localized resource of type System.Drawing.Bitmap.
///
- internal static System.Drawing.Bitmap MergeImage {
+ public static System.Drawing.Bitmap MergeImage {
get {
object obj = ResourceManager.GetObject("MergeImage", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
@@ -91,7 +91,7 @@ internal static System.Drawing.Bitmap MergeImage {
///
/// Looks up a localized string similar to My recent changesets.
///
- internal static string RecentChangesetSectionName {
+ public static string RecentChangesetSectionName {
get {
return ResourceManager.GetString("RecentChangesetSectionName", resourceCulture);
}
diff --git a/src/AutoMerge/Resources.resx b/src/AutoMerge/Resources.resx
index 2fe8727..4a71fee 100644
--- a/src/AutoMerge/Resources.resx
+++ b/src/AutoMerge/Resources.resx
@@ -118,7 +118,7 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- Intact Auto Merge
+ GenetiQ Auto Merge
My recent changesets
diff --git a/src/AutoMerge/Services/ChangesetService.cs b/src/AutoMerge/Services/ChangesetService.cs
index 612c2a7..437176e 100644
--- a/src/AutoMerge/Services/ChangesetService.cs
+++ b/src/AutoMerge/Services/ChangesetService.cs
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
using Microsoft.TeamFoundation.VersionControl.Client;
@@ -16,6 +16,7 @@ public ChangesetService(VersionControlServer versionControlServer)
public ICollection GetUserChangesets(string teamProjectName, string userName, int count)
{
var path = "$/" + teamProjectName;
+
return _versionControlServer.QueryHistory(path,
VersionSpec.Latest,
0,
diff --git a/src/AutoMerge/VSCommandTable.vsct b/src/AutoMerge/VSCommandTable.vsct
index 13dc40b..0a193b9 100644
--- a/src/AutoMerge/VSCommandTable.vsct
+++ b/src/AutoMerge/VSCommandTable.vsct
@@ -37,7 +37,7 @@
specify the "language" attribute for the Strings tag. It is possible however to specify
different String sections inside any element definition, one for each supported language.
-->
- Auto Merge
+ GenetiQ Auto Merge
@@ -46,6 +46,9 @@
+
@@ -57,14 +60,49 @@
IconIsMoniker
AutoMerge.Show
- Show Auto Merge
+ GenetiQ Auto Merge
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+