OSDN Git Service

add contrib dir
[tortoisegit/TortoiseGitJp.git] / contrib / issue-tracker-plugins / issue-tracker-plugins.txt
diff --git a/contrib/issue-tracker-plugins/issue-tracker-plugins.txt b/contrib/issue-tracker-plugins/issue-tracker-plugins.txt
new file mode 100644 (file)
index 0000000..aa2b7fc
--- /dev/null
@@ -0,0 +1,309 @@
+Issue Tracker Plugins\r
+=====================\r
+\r
+What is this for?\r
+-----------------\r
+\r
+Imagine the following scenario:\r
+\r
+ 1. Marvin the manager assigns a ticket or task to Dave, the developer, using\r
+    the issue-tracking or task-management software.\r
+ 2. Dave looks at his list of tasks using the issue-tracking software's front\r
+    end (i.e. a web-dashboard). He picks something to work on this morning.\r
+ 3. Dave fires up Visual Studio; hacks on some code; does some work toward\r
+    the task.\r
+ 4. Dave brings up TSVN's commit dialog. He types in a comment that lists,\r
+    depending on coding standards:\r
+     a) The ticket/task number of what he's been working on.\r
+     b) Some comments about what he's changed.\r
+ 5. He clicks OK, and his changes are committed to the repository.\r
+ 6. The issue-tracking software monitors the SVN repository, watching for\r
+    commits.It sees Dave's commit message, extracts the information from it,\r
+    and updates the ticket appropriately.\r
+ 7. Marvin looks in the task-management software, and can monitor the\r
+    project's progress.\r
+\r
+As it stands, TSVN supports (most of) this admirably. For example, with the\r
+Trac integration, I can put "See #43" or "Fixes #99" somewhere in the commit\r
+message, and Trac's post-commit hook will update the tickets accordingly.\r
+\r
+However:\r
+ 1. Dave has to keep the issue-tracker front-end open in order to look up the\r
+    ticket numbers.\r
+ 2. Some issue trackers want more information (e.g. time spent, time\r
+    remaining), and it needs to be formatted more rigidly.\r
+\r
+So, the user story looks like this:\r
+\r
+ "From the TSVN commit dialog, the user should be able to display up a list of\r
+  assigned tickets from the issue-tracker associated with that repository. The\r
+  user should be able to pick one or more tasks from this list."\r
+  \r
+ "This will populate the commit message with the information required by the\r
+  issue-tracker's SVN server-side post-commit hook."\r
+\r
+ "This functionality should be available from the commit dialog, because the\r
+  user may wish to choose which files to commit based on which ticket they\r
+  select, or he may wish to refresh his memory about what's changed before\r
+  selecting the appropriate ticket."\r
+\r
+\r
+Implementing an issue tracker plugin\r
+------------------------------------\r
+\r
+To write an integration plugin, you implement the IBugTraqProvider COM\r
+interface, and register your object as implementing the "TortoiseSVN BugTraq\r
+Providers" component category. This registration makes it easy for the\r
+settings dialog to find a list of available plugins.\r
+\r
+The IBugTraqProvider interface is documented in the inc\IBugTraqProvider.idl\r
+file.\r
+\r
+The component category is defined (in C++) as follows:\r
+\r
+// {3494FA92-B139-4730-9591-01135D5E7831}\r
+DEFINE_GUID(CATID_BugTraqProvider, \r
+                       0x3494fa92, 0xb139, 0x4730, 0x95, 0x91, 0x1, 0x13, 0x5d, 0x5e, 0x78, 0x31);\r
+\r
+\r
+Example Plugins\r
+---------------\r
+\r
+There are two example plugins in this folder.\r
+\r
+ - ExampleAtlPlugin, written in C++, using ATL.\r
+ - ExampleCsPlugin, written in C#.\r
\r
+They get the list of available "issues" from a hard-coded list, rather than a\r
+database or web service, but this should be sufficient to demonstrate the\r
+plugin API.\r
+\r
+\r
+Licensing and GPL compatibility\r
+-------------------------------\r
+\r
+TortoiseSVN is licensed under the GNU General Public License (see the file\r
+LICENSE for details).\r
+\r
+There is a specific exception for plugins that implement the issue tracker\r
+plugin interfaces; these do not need to be GPL-licensed.\r
+\r
+\r
+The IBugTraqProvider interface\r
+------------------------------\r
+\r
+In the contrib\issue-tracker-plugins\inc directory, you'll find the following\r
+files:\r
+\r
+ * IBugTraqProvider.idl\r
+   This is a copy of the src\IBugTraqProvider\IBugTraqProvider.idl file; it's\r
+   provided for reference; you'll probably use the files below.\r
+   \r
+ * IBugTraqProvider_h.h, IBugTraqProvider_i.c\r
+   These are the files you'll probably use if you implement a plugin in C++.\r
+\r
+ * Interop.BugTraqProvider.dll\r
+   Interop Assembly for implementing plugins in .NET. It's not a Primary\r
+   Interop Assembly (PIA).\r
+   The source code for this project is in the Interop.BugTraqProvider folder.\r
+\r
+The interface is documented in the .IDL file.\r
+\r
+\r
+Walkthrough: Creating an issue tracker plugin in C#\r
+---------------------------------------------------\r
+\r
+(This assumes a basic familiarity with creating Windows Forms applications).\r
+\r
+In Visual Studio 2005 or 2008, create a new "Class Library" project; give it a\r
+name.\r
+\r
+Delete the "Class1" class; we'll create another one in a moment.\r
+\r
+Add a reference to the inc\Interop.BugTraqProvider.dll file.\r
+\r
+Create a new class named "MyPlugin".\r
+\r
+Derive MyPlugin from the Interop.BugTraqProvider.IBugTraqProvider interface,\r
+and then implement the first two methods as follows:\r
+\r
+The ValidateParameters method should look like this:\r
+\r
+    public bool ValidateParameters(IntPtr hParentWnd, string parameters)\r
+    {\r
+        return true;\r
+    }\r
+\r
+The GetLinkText method should look like this:\r
+\r
+    public string GetLinkText(IntPtr hParentWnd, string parameters)\r
+    {\r
+        return "Choose Issue";\r
+    }\r
+\r
+We'll come back to GetCommitMessage shortly.\r
+\r
+The class also needs some attributes; it should look like this:\r
+\r
+    [ComVisible(true),\r
+     Guid("PUT-GUID-HERE"),\r
+     ClassInterface(ClassInterfaceType.None)]\r
+    public class Provider : IBugTraqProvider\r
+    {\r
+               // etc.\r
+\r
+(Replace "PUT-GUID-HERE" with a new GUID).\r
+\r
+Add a class to hold our example ticket data:\r
+\r
+       internal class TicketItem\r
+       {\r
+               private readonly int _ticketNumber;\r
+               private readonly string _ticketSummary;\r
+\r
+               public TicketItem(int ticketNumber, string ticketSummary)\r
+               {\r
+                       _ticketNumber = ticketNumber;\r
+                       _ticketSummary = ticketSummary;\r
+               }\r
+\r
+               public int Number\r
+               {\r
+                       get { return _ticketNumber; }\r
+               }\r
+\r
+               public string Summary\r
+               {\r
+                       get { return _ticketSummary; }\r
+               }\r
+       }\r
+\r
+We can now implement the GetCommitMessage method as follows:\r
+\r
+    public string GetCommitMessage(IntPtr hParentWnd, string parameters, string commonRoot, string[] pathList, string originalMessage)\r
+    {\r
+        List<TicketItem> tickets = new List<TicketItem>();\r
+        tickets.Add(new TicketItem(12, "Service doesn't start on Windows Vista"));\r
+        tickets.Add(new TicketItem(19, "About box doesn't render correctly in large fonts mode"));\r
+\r
+        MyIssuesForm form = new MyIssuesForm(tickets);\r
+        if (form.ShowDialog() != DialogResult.OK)\r
+            return originalMessage;\r
+\r
+        StringBuilder result = new StringBuilder(originalMessage);\r
+        if (originalMessage.Length != 0 && !originalMessage.EndsWith("\n"))\r
+            result.AppendLine();\r
+\r
+        foreach (TicketItem ticket in form.TicketsFixed)\r
+        {\r
+            result.AppendFormat("Fixed #{0}: {1}", ticket.Number, ticket.Summary);\r
+            result.AppendLine();\r
+        }\r
+\r
+        return result.ToString();\r
+    }\r
+\r
+This passes the list of open issues to the MyIssuesForm object, where the\r
+user will be able to check those ones that she's fixed. These are available\r
+through the TicketsFixed property.\r
+\r
+We use these to build a string that looks something like this:\r
+\r
+Fixed #12: Service doesn't start on Windows Vista.\r
+\r
+A commit message formatted like this will cause, (e.g.) Trac's post-commit\r
+hook to close the tickets.\r
+\r
+Anything that the user has already entered into the commit message is left\r
+there.\r
+\r
+Now we need a dialog box that displays the issues assigned to the\r
+current user.\r
+\r
+Add a Windows Form item to your project. Name it "MyIssuesForm". Set the\r
+following properties:\r
+\r
+ StartPosition = CenterParent\r
+ MaximizeBox = False\r
+ MinimizeBox = False\r
+ ShowIcon = False\r
+ ShowInTaskbar = False\r
+\r
+Put the usual OK and Cancel buttons on it; arrange them and wire them up\r
+properly.\r
+\r
+Add a ListView control to the form and arrange it appropriately. Set the\r
+following properties:\r
+\r
+ Checkboxes = True\r
+ FullRowSelect = True\r
+ View = Details\r
+ HeaderStyle = Nonclickable\r
+\r
+Change the class so that it looks like this:\r
+\r
+       partial class MyIssuesForm : Form\r
+       {\r
+               private readonly IEnumerable<TicketItem> _tickets;\r
+               private readonly List<TicketItem> _ticketsAffected = new List<TicketItem>();\r
+\r
+               public MyIssuesForm(IEnumerable<TicketItem> tickets)\r
+               {\r
+                       InitializeComponent();\r
+                       _tickets = tickets;\r
+               }\r
+\r
+               public IEnumerable<TicketItem> TicketsFixed\r
+               {\r
+                       get { return _ticketsAffected; }\r
+               }\r
+\r
+               // etc.\r
+\r
+Then implement some event handlers in MyIssuesForm as follows:\r
+\r
+        private void MyIssuesForm_Load(object sender, EventArgs e)\r
+        {\r
+            listView1.Columns.Add("");\r
+            listView1.Columns.Add("#");\r
+            listView1.Columns.Add("Summary");\r
+\r
+            foreach(TicketItem ticketItem in _tickets)\r
+            {\r
+                ListViewItem lvi = new ListViewItem();\r
+                lvi.Text = "";\r
+                lvi.SubItems.Add(ticketItem.Number.ToString());\r
+                lvi.SubItems.Add(ticketItem.Summary);\r
+                lvi.Tag = ticketItem;\r
+\r
+                listView1.Items.Add(lvi);\r
+            }\r
+\r
+            listView1.Columns[0].Width = -1;\r
+            listView1.Columns[1].Width = -1;\r
+            listView1.Columns[2].Width = -1;\r
+        }\r
+\r
+        private void okButton_Click(object sender, EventArgs e)\r
+        {\r
+            foreach (ListViewItem lvi in listView1.Items)\r
+            {\r
+                TicketItem ticketItem = lvi.Tag as TicketItem;\r
+                if (ticketItem != null && lvi.Checked)\r
+                    _ticketsAffected.Add(ticketItem);\r
+            }\r
+        }\r
+\r
+Registering your new C# class can be done by using RegAsm from the command\r
+line, as follows:\r
+\r
+       RegAsm bin\Debug\MyCsPlugin.dll /codebase /regfile:MyCsPlugin.reg\r
+\r
+You'll need to edit the .REG file, by adding another "Implemented Categories"\r
+entry that looks like this:\r
+\r
+[HKEY_CLASSES_ROOT\CLSID\{PUT-GUID-HERE}\Implemented Categories\{3494FA92-B139-4730-9591-01135D5E7831}]\r
+\r
+Replace "PUT-GUID-HERE" with the same value you used earlier.\r
+\r
+Then, merge that .REG file into the registry, and your plugin is ready to go!\r