diff options
author | Lluis Sanchez Gual <lluis@xamarin.com> | 2015-05-19 11:53:39 +0300 |
---|---|---|
committer | Lluis Sanchez Gual <lluis@xamarin.com> | 2015-05-19 11:53:39 +0300 |
commit | b48eb3858777967118ad6da0c45eec99b11c5352 (patch) | |
tree | 17b5cf0ed4d58de96d0e931fa8aa469139801b4c | |
parent | 76fbffec7c1999df166956e14ac6a4b92d9d649a (diff) | |
parent | dae48b57cbd7886e32d4a9b7ba7c982ce80ef714 (diff) |
Merge remote-tracking branch 'origin/master' into roslyn
74 files changed, 2559 insertions, 3687 deletions
diff --git a/.gitmodules b/.gitmodules index 9968c3156b..f2b80ffddf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,9 +5,6 @@ [submodule "main/external/mono-tools"] path = main/external/mono-tools url = git://github.com/mono/mono-tools.git -[submodule "main/external/ngit"] - path = main/external/ngit - url = git://github.com/mono/ngit.git [submodule "main/external/mdtestharness"] path = main/external/mdtestharness url = git://github.com/mono/mdtestharness.git @@ -51,3 +48,9 @@ [submodule "main/external/sharpsvn-binary"] path = main/external/sharpsvn-binary url = git://github.com/mono/sharpsvn-binary.git +[submodule "main/external/libgit2sharp"] + path = main/external/libgit2sharp + url = git://github.com/libgit2/libgit2sharp.git +[submodule "main/external/libgit-binary"] + path = main/external/libgit-binary + url = git://github.com/mono/libgit-binary.git @@ -80,6 +80,8 @@ Dependencies Gtk# >= 2.12.8 monodoc >= 1.0 mono-addins >= 0.6 + cmake (Linux only for git support) + libssh2 (Linux only for git support) Special Environment Variables ----------------------------- diff --git a/main/Main.sln b/main/Main.sln index 1577463cbc..108e078692 100644 --- a/main/Main.sln +++ b/main/Main.sln @@ -227,16 +227,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xwt.Gtk.Windows", "external EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xwt.XamMac", "external\xwt\Xwt.XamMac\Xwt.XamMac.csproj", "{B7C1673E-5124-4BE5-8D21-EC8B12F85B6B}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NGit", "NGit", "{08AC1C52-707A-46D1-AD72-36D747991592}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NGit", "external\ngit\NGit\NGit.csproj", "{E3BFF8B4-189C-496A-A817-7E8B31E22B91}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sharpen.Unix", "external\ngit\Sharpen.Unix\Sharpen.Unix.csproj", "{849AE05D-0058-4A8C-A0E8-77DC6BB12E52}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sharpen", "external\ngit\Sharpen\Sharpen.csproj", "{72944A6C-45FF-4EF8-B349-8C9CABF519D4}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NSch", "external\ngit\NSch\NSch.csproj", "{A19E6F3F-A25B-4B01-8922-CF0CC35C781D}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mono.Cecil", "Mono.Cecil", "{D07C8309-996F-484E-BDA1-26BBAF69D29B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil", "external\cecil\Mono.Cecil.csproj", "{D68133BD-1E63-496E-9EDE-4FBDBF77B486}"
@@ -281,6 +271,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NR6Pack", "external\NRefact EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GuiUnit_NET_4_5", "external\guiunit\src\framework\GuiUnit_NET_4_5.csproj", "{D12F0F7B-8DE3-43EC-BA49-41052D065A9B}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibGit2Sharp", "external\libgit2sharp\LibGit2Sharp\LibGit2Sharp.csproj", "{EE6ED99F-CB12-4683-B055-D28FC7357A34}" +EndProject Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "po", "po\po.mdproj", "{AC7D119C-980B-4712-8811-5368C14412D7}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{5D3F7E65-E55B-45CA-A83B-D1E10040281E}"
@@ -326,12 +318,12 @@ Global GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0413DB7D-8B35-423F-9752-D75C9225E7DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0413DB7D-8B35-423F-9752-D75C9225E7DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {0413DB7D-8B35-423F-9752-D75C9225E7DE}.DebugGnome|Any CPU.ActiveCfg = Debug|Any CPU
- {0413DB7D-8B35-423F-9752-D75C9225E7DE}.DebugGnome|Any CPU.Build.0 = Debug|Any CPU
- {0413DB7D-8B35-423F-9752-D75C9225E7DE}.DebugMac|Any CPU.ActiveCfg = Debug|Any CPU
- {0413DB7D-8B35-423F-9752-D75C9225E7DE}.DebugMac|Any CPU.Build.0 = Debug|Any CPU
- {0413DB7D-8B35-423F-9752-D75C9225E7DE}.DebugWin32|Any CPU.ActiveCfg = Debug|Any CPU
- {0413DB7D-8B35-423F-9752-D75C9225E7DE}.DebugWin32|Any CPU.Build.0 = Debug|Any CPU
+ {0413DB7D-8B35-423F-9752-D75C9225E7DE}.DebugGnome|Any CPU.ActiveCfg = DebugGnome|Any CPU + {0413DB7D-8B35-423F-9752-D75C9225E7DE}.DebugGnome|Any CPU.Build.0 = DebugGnome|Any CPU + {0413DB7D-8B35-423F-9752-D75C9225E7DE}.DebugMac|Any CPU.ActiveCfg = DebugMac|Any CPU + {0413DB7D-8B35-423F-9752-D75C9225E7DE}.DebugMac|Any CPU.Build.0 = DebugMac|Any CPU + {0413DB7D-8B35-423F-9752-D75C9225E7DE}.DebugWin32|Any CPU.ActiveCfg = DebugWin32|Any CPU + {0413DB7D-8B35-423F-9752-D75C9225E7DE}.DebugWin32|Any CPU.Build.0 = DebugWin32|Any CPU {0413DB7D-8B35-423F-9752-D75C9225E7DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0413DB7D-8B35-423F-9752-D75C9225E7DE}.Release|Any CPU.Build.0 = Release|Any CPU
{0413DB7D-8B35-423F-9752-D75C9225E7DE}.ReleaseGnome|Any CPU.ActiveCfg = Release|Any CPU
@@ -847,22 +839,6 @@ Global {69136056-BFD3-4CEC-BB41-D9991C79593C}.ReleaseMac|Any CPU.ActiveCfg = Release|Any CPU
{69136056-BFD3-4CEC-BB41-D9991C79593C}.ReleaseWin32|Any CPU.ActiveCfg = Release|Any CPU
{69136056-BFD3-4CEC-BB41-D9991C79593C}.ReleaseWin32|Any CPU.Build.0 = Release|Any CPU
- {72944A6C-45FF-4EF8-B349-8C9CABF519D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {72944A6C-45FF-4EF8-B349-8C9CABF519D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {72944A6C-45FF-4EF8-B349-8C9CABF519D4}.DebugGnome|Any CPU.ActiveCfg = Debug|Any CPU
- {72944A6C-45FF-4EF8-B349-8C9CABF519D4}.DebugGnome|Any CPU.Build.0 = Debug|Any CPU
- {72944A6C-45FF-4EF8-B349-8C9CABF519D4}.DebugMac|Any CPU.ActiveCfg = Debug|Any CPU
- {72944A6C-45FF-4EF8-B349-8C9CABF519D4}.DebugMac|Any CPU.Build.0 = Debug|Any CPU
- {72944A6C-45FF-4EF8-B349-8C9CABF519D4}.DebugWin32|Any CPU.ActiveCfg = Debug|Any CPU
- {72944A6C-45FF-4EF8-B349-8C9CABF519D4}.DebugWin32|Any CPU.Build.0 = Debug|Any CPU
- {72944A6C-45FF-4EF8-B349-8C9CABF519D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {72944A6C-45FF-4EF8-B349-8C9CABF519D4}.Release|Any CPU.Build.0 = Release|Any CPU
- {72944A6C-45FF-4EF8-B349-8C9CABF519D4}.ReleaseGnome|Any CPU.ActiveCfg = Release|Any CPU
- {72944A6C-45FF-4EF8-B349-8C9CABF519D4}.ReleaseGnome|Any CPU.Build.0 = Release|Any CPU
- {72944A6C-45FF-4EF8-B349-8C9CABF519D4}.ReleaseMac|Any CPU.ActiveCfg = Release|Any CPU
- {72944A6C-45FF-4EF8-B349-8C9CABF519D4}.ReleaseMac|Any CPU.Build.0 = Release|Any CPU
- {72944A6C-45FF-4EF8-B349-8C9CABF519D4}.ReleaseWin32|Any CPU.ActiveCfg = Release|Any CPU
- {72944A6C-45FF-4EF8-B349-8C9CABF519D4}.ReleaseWin32|Any CPU.Build.0 = Release|Any CPU
{73D4CC8B-BAB9-4A29-841B-F25C6311F067}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{73D4CC8B-BAB9-4A29-841B-F25C6311F067}.Debug|Any CPU.Build.0 = Debug|Any CPU
{73D4CC8B-BAB9-4A29-841B-F25C6311F067}.DebugGnome|Any CPU.ActiveCfg = Debug|Any CPU
@@ -987,22 +963,6 @@ Global {7FCDB0D9-AA7D-44E4-BE74-55312B432389}.ReleaseMac|Any CPU.Build.0 = Release|Any CPU
{7FCDB0D9-AA7D-44E4-BE74-55312B432389}.ReleaseWin32|Any CPU.ActiveCfg = Release|Any CPU
{7FCDB0D9-AA7D-44E4-BE74-55312B432389}.ReleaseWin32|Any CPU.Build.0 = Release|Any CPU
- {849AE05D-0058-4A8C-A0E8-77DC6BB12E52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {849AE05D-0058-4A8C-A0E8-77DC6BB12E52}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {849AE05D-0058-4A8C-A0E8-77DC6BB12E52}.DebugGnome|Any CPU.ActiveCfg = Debug|Any CPU
- {849AE05D-0058-4A8C-A0E8-77DC6BB12E52}.DebugGnome|Any CPU.Build.0 = Debug|Any CPU
- {849AE05D-0058-4A8C-A0E8-77DC6BB12E52}.DebugMac|Any CPU.ActiveCfg = Debug|Any CPU
- {849AE05D-0058-4A8C-A0E8-77DC6BB12E52}.DebugMac|Any CPU.Build.0 = Debug|Any CPU
- {849AE05D-0058-4A8C-A0E8-77DC6BB12E52}.DebugWin32|Any CPU.ActiveCfg = Debug|Any CPU
- {849AE05D-0058-4A8C-A0E8-77DC6BB12E52}.DebugWin32|Any CPU.Build.0 = Debug|Any CPU
- {849AE05D-0058-4A8C-A0E8-77DC6BB12E52}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {849AE05D-0058-4A8C-A0E8-77DC6BB12E52}.Release|Any CPU.Build.0 = Release|Any CPU
- {849AE05D-0058-4A8C-A0E8-77DC6BB12E52}.ReleaseGnome|Any CPU.ActiveCfg = Release|Any CPU
- {849AE05D-0058-4A8C-A0E8-77DC6BB12E52}.ReleaseGnome|Any CPU.Build.0 = Release|Any CPU
- {849AE05D-0058-4A8C-A0E8-77DC6BB12E52}.ReleaseMac|Any CPU.ActiveCfg = Release|Any CPU
- {849AE05D-0058-4A8C-A0E8-77DC6BB12E52}.ReleaseMac|Any CPU.Build.0 = Release|Any CPU
- {849AE05D-0058-4A8C-A0E8-77DC6BB12E52}.ReleaseWin32|Any CPU.ActiveCfg = Release|Any CPU
- {849AE05D-0058-4A8C-A0E8-77DC6BB12E52}.ReleaseWin32|Any CPU.Build.0 = Release|Any CPU
{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU
{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU
{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.DebugGnome|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU
@@ -1276,22 +1236,6 @@ Global {9FBCC262-10DC-4E84-A5C4-17230BBF8862}.ReleaseMac|Any CPU.ActiveCfg = Release|Any CPU
{9FBCC262-10DC-4E84-A5C4-17230BBF8862}.ReleaseWin32|Any CPU.ActiveCfg = Release|Any CPU
{9FBCC262-10DC-4E84-A5C4-17230BBF8862}.ReleaseWin32|Any CPU.Build.0 = Release|Any CPU
- {A19E6F3F-A25B-4B01-8922-CF0CC35C781D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {A19E6F3F-A25B-4B01-8922-CF0CC35C781D}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {A19E6F3F-A25B-4B01-8922-CF0CC35C781D}.DebugGnome|Any CPU.ActiveCfg = Debug|Any CPU
- {A19E6F3F-A25B-4B01-8922-CF0CC35C781D}.DebugGnome|Any CPU.Build.0 = Debug|Any CPU
- {A19E6F3F-A25B-4B01-8922-CF0CC35C781D}.DebugMac|Any CPU.ActiveCfg = Debug|Any CPU
- {A19E6F3F-A25B-4B01-8922-CF0CC35C781D}.DebugMac|Any CPU.Build.0 = Debug|Any CPU
- {A19E6F3F-A25B-4B01-8922-CF0CC35C781D}.DebugWin32|Any CPU.ActiveCfg = Debug|Any CPU
- {A19E6F3F-A25B-4B01-8922-CF0CC35C781D}.DebugWin32|Any CPU.Build.0 = Debug|Any CPU
- {A19E6F3F-A25B-4B01-8922-CF0CC35C781D}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {A19E6F3F-A25B-4B01-8922-CF0CC35C781D}.Release|Any CPU.Build.0 = Release|Any CPU
- {A19E6F3F-A25B-4B01-8922-CF0CC35C781D}.ReleaseGnome|Any CPU.ActiveCfg = Release|Any CPU
- {A19E6F3F-A25B-4B01-8922-CF0CC35C781D}.ReleaseGnome|Any CPU.Build.0 = Release|Any CPU
- {A19E6F3F-A25B-4B01-8922-CF0CC35C781D}.ReleaseMac|Any CPU.ActiveCfg = Release|Any CPU
- {A19E6F3F-A25B-4B01-8922-CF0CC35C781D}.ReleaseMac|Any CPU.Build.0 = Release|Any CPU
- {A19E6F3F-A25B-4B01-8922-CF0CC35C781D}.ReleaseWin32|Any CPU.ActiveCfg = Release|Any CPU
- {A19E6F3F-A25B-4B01-8922-CF0CC35C781D}.ReleaseWin32|Any CPU.Build.0 = Release|Any CPU
{A2329308-3751-4DBD-9A75-5F7B8B024625}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A2329308-3751-4DBD-9A75-5F7B8B024625}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A2329308-3751-4DBD-9A75-5F7B8B024625}.DebugGnome|Any CPU.ActiveCfg = Debug|Any CPU
@@ -1796,22 +1740,6 @@ Global {E2CAB397-D00C-4D11-8F5F-E3A052092969}.ReleaseMac|Any CPU.ActiveCfg = ReleaseMac|Any CPU
{E2CAB397-D00C-4D11-8F5F-E3A052092969}.ReleaseMac|Any CPU.Build.0 = ReleaseMac|Any CPU
{E2CAB397-D00C-4D11-8F5F-E3A052092969}.ReleaseWin32|Any CPU.ActiveCfg = Release|Any CPU
- {E3BFF8B4-189C-496A-A817-7E8B31E22B91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {E3BFF8B4-189C-496A-A817-7E8B31E22B91}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {E3BFF8B4-189C-496A-A817-7E8B31E22B91}.DebugGnome|Any CPU.ActiveCfg = Debug|Any CPU
- {E3BFF8B4-189C-496A-A817-7E8B31E22B91}.DebugGnome|Any CPU.Build.0 = Debug|Any CPU
- {E3BFF8B4-189C-496A-A817-7E8B31E22B91}.DebugMac|Any CPU.ActiveCfg = Debug|Any CPU
- {E3BFF8B4-189C-496A-A817-7E8B31E22B91}.DebugMac|Any CPU.Build.0 = Debug|Any CPU
- {E3BFF8B4-189C-496A-A817-7E8B31E22B91}.DebugWin32|Any CPU.ActiveCfg = Debug|Any CPU
- {E3BFF8B4-189C-496A-A817-7E8B31E22B91}.DebugWin32|Any CPU.Build.0 = Debug|Any CPU
- {E3BFF8B4-189C-496A-A817-7E8B31E22B91}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {E3BFF8B4-189C-496A-A817-7E8B31E22B91}.Release|Any CPU.Build.0 = Release|Any CPU
- {E3BFF8B4-189C-496A-A817-7E8B31E22B91}.ReleaseGnome|Any CPU.ActiveCfg = Release|Any CPU
- {E3BFF8B4-189C-496A-A817-7E8B31E22B91}.ReleaseGnome|Any CPU.Build.0 = Release|Any CPU
- {E3BFF8B4-189C-496A-A817-7E8B31E22B91}.ReleaseMac|Any CPU.ActiveCfg = Release|Any CPU
- {E3BFF8B4-189C-496A-A817-7E8B31E22B91}.ReleaseMac|Any CPU.Build.0 = Release|Any CPU
- {E3BFF8B4-189C-496A-A817-7E8B31E22B91}.ReleaseWin32|Any CPU.ActiveCfg = Release|Any CPU
- {E3BFF8B4-189C-496A-A817-7E8B31E22B91}.ReleaseWin32|Any CPU.Build.0 = Release|Any CPU
{E95833C9-90AA-4366-9262-0A1BED148249}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E95833C9-90AA-4366-9262-0A1BED148249}.DebugGnome|Any CPU.ActiveCfg = Debug|Any CPU
{E95833C9-90AA-4366-9262-0A1BED148249}.DebugMac|Any CPU.ActiveCfg = Debug|Any CPU
@@ -1838,6 +1766,22 @@ Global {EBFC7F90-C2E5-4A4C-A327-E35021BEC181}.ReleaseMac|Any CPU.Build.0 = Release|Any CPU
{EBFC7F90-C2E5-4A4C-A327-E35021BEC181}.ReleaseWin32|Any CPU.ActiveCfg = Release|Any CPU
{EBFC7F90-C2E5-4A4C-A327-E35021BEC181}.ReleaseWin32|Any CPU.Build.0 = Release|Any CPU
+ {EE6ED99F-CB12-4683-B055-D28FC7357A34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EE6ED99F-CB12-4683-B055-D28FC7357A34}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EE6ED99F-CB12-4683-B055-D28FC7357A34}.DebugGnome|Any CPU.ActiveCfg = Debug|Any CPU + {EE6ED99F-CB12-4683-B055-D28FC7357A34}.DebugGnome|Any CPU.Build.0 = Debug|Any CPU + {EE6ED99F-CB12-4683-B055-D28FC7357A34}.DebugMac|Any CPU.ActiveCfg = Debug|Any CPU + {EE6ED99F-CB12-4683-B055-D28FC7357A34}.DebugMac|Any CPU.Build.0 = Debug|Any CPU + {EE6ED99F-CB12-4683-B055-D28FC7357A34}.DebugWin32|Any CPU.ActiveCfg = Debug|Any CPU + {EE6ED99F-CB12-4683-B055-D28FC7357A34}.DebugWin32|Any CPU.Build.0 = Debug|Any CPU + {EE6ED99F-CB12-4683-B055-D28FC7357A34}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EE6ED99F-CB12-4683-B055-D28FC7357A34}.Release|Any CPU.Build.0 = Release|Any CPU + {EE6ED99F-CB12-4683-B055-D28FC7357A34}.ReleaseGnome|Any CPU.ActiveCfg = Release|Any CPU + {EE6ED99F-CB12-4683-B055-D28FC7357A34}.ReleaseGnome|Any CPU.Build.0 = Release|Any CPU + {EE6ED99F-CB12-4683-B055-D28FC7357A34}.ReleaseMac|Any CPU.ActiveCfg = Release|Any CPU + {EE6ED99F-CB12-4683-B055-D28FC7357A34}.ReleaseMac|Any CPU.Build.0 = Release|Any CPU + {EE6ED99F-CB12-4683-B055-D28FC7357A34}.ReleaseWin32|Any CPU.ActiveCfg = Release|Any CPU + {EE6ED99F-CB12-4683-B055-D28FC7357A34}.ReleaseWin32|Any CPU.Build.0 = Release|Any CPU {EF91D0B8-53F6-4622-9F26-3ED27815878A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EF91D0B8-53F6-4622-9F26-3ED27815878A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EF91D0B8-53F6-4622-9F26-3ED27815878A}.DebugGnome|Any CPU.ActiveCfg = Debug|Any CPU
@@ -1872,12 +1816,12 @@ Global {F218643D-2E74-4309-820E-206A54B7133F}.ReleaseWin32|Any CPU.Build.0 = Release|Any CPU
{F3AC14B0-3D1F-4B9B-95E8-384056060F33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F3AC14B0-3D1F-4B9B-95E8-384056060F33}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {F3AC14B0-3D1F-4B9B-95E8-384056060F33}.DebugGnome|Any CPU.ActiveCfg = Debug|Any CPU
- {F3AC14B0-3D1F-4B9B-95E8-384056060F33}.DebugGnome|Any CPU.Build.0 = Debug|Any CPU
- {F3AC14B0-3D1F-4B9B-95E8-384056060F33}.DebugMac|Any CPU.ActiveCfg = Debug|Any CPU
- {F3AC14B0-3D1F-4B9B-95E8-384056060F33}.DebugMac|Any CPU.Build.0 = Debug|Any CPU
- {F3AC14B0-3D1F-4B9B-95E8-384056060F33}.DebugWin32|Any CPU.ActiveCfg = Debug|Any CPU
- {F3AC14B0-3D1F-4B9B-95E8-384056060F33}.DebugWin32|Any CPU.Build.0 = Debug|Any CPU
+ {F3AC14B0-3D1F-4B9B-95E8-384056060F33}.DebugGnome|Any CPU.ActiveCfg = DebugGnome|Any CPU + {F3AC14B0-3D1F-4B9B-95E8-384056060F33}.DebugGnome|Any CPU.Build.0 = DebugGnome|Any CPU + {F3AC14B0-3D1F-4B9B-95E8-384056060F33}.DebugMac|Any CPU.ActiveCfg = DebugMac|Any CPU + {F3AC14B0-3D1F-4B9B-95E8-384056060F33}.DebugMac|Any CPU.Build.0 = DebugMac|Any CPU + {F3AC14B0-3D1F-4B9B-95E8-384056060F33}.DebugWin32|Any CPU.ActiveCfg = DebugWin32|Any CPU + {F3AC14B0-3D1F-4B9B-95E8-384056060F33}.DebugWin32|Any CPU.Build.0 = DebugWin32|Any CPU {F3AC14B0-3D1F-4B9B-95E8-384056060F33}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F3AC14B0-3D1F-4B9B-95E8-384056060F33}.Release|Any CPU.Build.0 = Release|Any CPU
{F3AC14B0-3D1F-4B9B-95E8-384056060F33}.ReleaseGnome|Any CPU.ActiveCfg = Release|Any CPU
@@ -2086,22 +2030,18 @@ Global {A9AE40FF-1A21-414A-9FE7-3BE13644CC6D} = {F12939F1-D55A-4CE9-9F33-8D959BFC7D6C}
{4CB170EF-DFE6-4A56-9E1B-A85449E827A7} = {F12939F1-D55A-4CE9-9F33-8D959BFC7D6C}
{67A32B53-F719-4ECB-B5E1-FD0B04FEE258} = {F12939F1-D55A-4CE9-9F33-8D959BFC7D6C}
- {08AC1C52-707A-46D1-AD72-36D747991592} = {F12939F1-D55A-4CE9-9F33-8D959BFC7D6C}
{D07C8309-996F-484E-BDA1-26BBAF69D29B} = {F12939F1-D55A-4CE9-9F33-8D959BFC7D6C}
{B8897B76-1A12-4DFA-8B60-7944CC4C9654} = {F12939F1-D55A-4CE9-9F33-8D959BFC7D6C}
{2D711139-8765-4929-BC7A-AA2DEE6F615D} = {F12939F1-D55A-4CE9-9F33-8D959BFC7D6C}
{840E8B8D-929C-4CB2-9D23-2702FF01269A} = {F12939F1-D55A-4CE9-9F33-8D959BFC7D6C}
{D12F0F7B-8DE3-43EC-BA49-41052D065A9B} = {F12939F1-D55A-4CE9-9F33-8D959BFC7D6C}
+ {EE6ED99F-CB12-4683-B055-D28FC7357A34} = {F12939F1-D55A-4CE9-9F33-8D959BFC7D6C} {92494904-35FA-4DC9-BDE9-3A3E87AC49D3} = {67A32B53-F719-4ECB-B5E1-FD0B04FEE258}
{C3887A93-B2BD-4097-8E2F-3A063EFF32FD} = {67A32B53-F719-4ECB-B5E1-FD0B04FEE258}
{C93D746E-1586-4D4F-B411-BF5A966E6A08} = {67A32B53-F719-4ECB-B5E1-FD0B04FEE258}
{E95833C9-90AA-4366-9262-0A1BED148249} = {67A32B53-F719-4ECB-B5E1-FD0B04FEE258}
{252117CA-0ABB-4F36-BFC8-DE23A8089BB9} = {67A32B53-F719-4ECB-B5E1-FD0B04FEE258}
{B7C1673E-5124-4BE5-8D21-EC8B12F85B6B} = {67A32B53-F719-4ECB-B5E1-FD0B04FEE258}
- {E3BFF8B4-189C-496A-A817-7E8B31E22B91} = {08AC1C52-707A-46D1-AD72-36D747991592}
- {849AE05D-0058-4A8C-A0E8-77DC6BB12E52} = {08AC1C52-707A-46D1-AD72-36D747991592}
- {72944A6C-45FF-4EF8-B349-8C9CABF519D4} = {08AC1C52-707A-46D1-AD72-36D747991592}
- {A19E6F3F-A25B-4B01-8922-CF0CC35C781D} = {08AC1C52-707A-46D1-AD72-36D747991592}
{D68133BD-1E63-496E-9EDE-4FBDBF77B486} = {D07C8309-996F-484E-BDA1-26BBAF69D29B}
{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD} = {D07C8309-996F-484E-BDA1-26BBAF69D29B}
{63E6915C-7EA4-4D76-AB28-0D7191EEA626} = {D07C8309-996F-484E-BDA1-26BBAF69D29B}
diff --git a/main/Makefile.am b/main/Makefile.am index 94059d3eff..4f8c22d2a5 100644 --- a/main/Makefile.am +++ b/main/Makefile.am @@ -156,7 +156,7 @@ test: cd tests && $(MAKE) test assembly=$(assembly) uitest: - cd tests && $(MAKE) uitest assembly=$(assembly) + cd tests && $(MAKE) uitest assembly=$(assembly) categories=$(categories) coverage: cd tests && $(MAKE) coverage diff --git a/main/configure.in b/main/configure.in index 9836404435..a9371febc3 100644 --- a/main/configure.in +++ b/main/configure.in @@ -232,6 +232,16 @@ fi AM_CONDITIONAL(ENABLE_WINDOWSPLATFORM, [test x$enable_windowsplatform = xyes]) +if test x$enable_gnomeplatform = xyes && test x$enable_git = xyes; then + AC_PATH_PROG(CMAKE, cmake, no) + if test "x$CMAKE" = "xno"; then + AC_MSG_ERROR([You need to install cmake for Git support to be built]) + fi + + PKG_CHECK_MODULES(LIBSSH2, libssh2) + AC_SUBST(LIBSSH2_LIBS) +fi + dnl Intl ALL_LINGUAS="cs da de es fr ja pt_BR tr pl it zh_TW zh_CN ru sl ca gl pt sv nl id hu nb ko uk" AC_SUBST(ALL_LINGUAS) diff --git a/main/contrib/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs b/main/contrib/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs index bf85ca94f4..5de51b9b1a 100644 --- a/main/contrib/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs +++ b/main/contrib/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs @@ -20,11 +20,9 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using ICSharpCode.Decompiler.FlowAnalysis; using ICSharpCode.NRefactory.Utils; using Mono.Cecil; using Mono.Cecil.Cil; -using Mono.CSharp; namespace ICSharpCode.Decompiler.ILAst { diff --git a/main/contrib/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs b/main/contrib/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs index 9cd42a14fc..7fd74a60e8 100644 --- a/main/contrib/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs +++ b/main/contrib/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs @@ -21,13 +21,10 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; -using System.Text; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.NRefactory.Utils; using Mono.Cecil; using Mono.Cecil.Cil; -using Mono.CSharp; using Cecil = Mono.Cecil; namespace ICSharpCode.Decompiler.ILAst diff --git a/main/external/libgit-binary b/main/external/libgit-binary new file mode 160000 +Subproject 65d641c93f5392c151788ebb466932b5c6181a7 diff --git a/main/external/libgit2sharp b/main/external/libgit2sharp new file mode 160000 +Subproject 71feabfe58a742e9913add3baadf87c27956e58 diff --git a/main/external/ngit b/main/external/ngit deleted file mode 160000 -Subproject 292a4e4ff81d1c4f59b04cd2b9bc1a1f588fa4e diff --git a/main/external/xwt b/main/external/xwt -Subproject 3815aa6fa5cc085eadaa84567c1d0cf9f66be4b +Subproject a987a4a0f633a91bfbb0d02e1f9768f0ba5c71f diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/TypeSystemProvider.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/TypeSystemProvider.cs index 037656f295..0a13bed30a 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/TypeSystemProvider.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/TypeSystemProvider.cs @@ -28,15 +28,10 @@ using MonoDevelop.Ide.TypeSystem; using System.Collections.Generic; using MonoDevelop.Projects; using MonoDevelop.CSharp.Project; -using Mono.CSharp; -using System.Linq; using MonoDevelop.Core; -using MonoDevelop.Ide.Editor; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using MonoDevelop.Core.Text; using System.Threading.Tasks; namespace MonoDevelop.CSharp.Parser diff --git a/main/src/addins/MacPlatform/Dialogs/MacSelectFileDialogHandler.cs b/main/src/addins/MacPlatform/Dialogs/MacSelectFileDialogHandler.cs index 227ff4e674..df97c89c96 100644 --- a/main/src/addins/MacPlatform/Dialogs/MacSelectFileDialogHandler.cs +++ b/main/src/addins/MacPlatform/Dialogs/MacSelectFileDialogHandler.cs @@ -109,6 +109,7 @@ namespace MonoDevelop.MacIntegration var openPanel = panel as NSOpenPanel; if (openPanel != null) { openPanel.AllowsMultipleSelection = data.SelectMultiple; + openPanel.ShowsHiddenFiles = data.ShowHidden; } } diff --git a/main/src/addins/MacPlatform/MainToolbar/CenteringSpace.cs b/main/src/addins/MacPlatform/MainToolbar/CenteringSpace.cs index 2ee1fcf81c..4684c43565 100644 --- a/main/src/addins/MacPlatform/MainToolbar/CenteringSpace.cs +++ b/main/src/addins/MacPlatform/MainToolbar/CenteringSpace.cs @@ -50,6 +50,7 @@ namespace MonoDevelop.MacIntegration.MainToolbar CenteringSpaceToolbarItem.WindowFullscreening = false; DispatchService.GuiDispatch (toolbarItem.UpdateWidth); }); + base.ViewDidMoveToWindow (); } } diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseGitRepositoryTests.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseGitRepositoryTests.cs index 36278fff7b..922ba2436b 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseGitRepositoryTests.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseGitRepositoryTests.cs @@ -1,390 +1,448 @@ -//
-// RepositoryTests.cs
-//
-// Author:
-// Therzok <teromario@yahoo.com>
-//
-// Copyright (c) 2013 Xamarin Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-using MonoDevelop.Core;
-using MonoDevelop.VersionControl;
-using MonoDevelop.VersionControl.Git;
-using MonoDevelop.VersionControl.Tests;
-using NGit;
-using NGit.Api;
-using NUnit.Framework;
-using System.IO;
-using NGit.Storage.File;
-using NGit.Revwalk;
-using System.Linq;
-
-namespace MonoDevelop.VersionControl.Git.Tests
-{
- [TestFixture]
- sealed class BaseGitUtilsTest : BaseRepoUtilsTest
- {
- [SetUp]
- public override void Setup ()
- {
- // Generate directories and a svn util.
- RemotePath = new FilePath (FileService.CreateTempDirectory () + Path.DirectorySeparatorChar);
- LocalPath = new FilePath (FileService.CreateTempDirectory () + Path.DirectorySeparatorChar);
- Directory.CreateDirectory (RemotePath.FullPath + "repo.git");
- RemoteUrl = "file:///" + RemotePath.FullPath + "repo.git";
-
- // Initialize the bare repo.
- var ci = new InitCommand ();
- ci.SetDirectory (new Sharpen.FilePath (RemotePath.FullPath + "repo.git"));
- ci.SetBare (true);
- ci.Call ();
- var bare = new FileRepository (new Sharpen.FilePath (RemotePath.FullPath + "repo.git"));
- string branch = Constants.R_HEADS + "master";
-
- RefUpdate head = bare.UpdateRef (Constants.HEAD);
- head.DisableRefLog ();
- head.Link (branch);
-
- // Check out the repository.
- Checkout (LocalPath, RemoteUrl);
- Repo = GetRepo (LocalPath, RemoteUrl);
- DotDir = ".git";
- }
-
- protected override NUnit.Framework.Constraints.IResolveConstraint IsCorrectType ()
- {
- return Is.InstanceOf<GitRepository> ();
- }
-
- protected override int RepoItemsCount {
- get { return 1; }
- }
-
- protected override int RepoItemsCountRecursive {
- get { return 13; }
- }
-
- protected override void TestDiff ()
- {
- string difftext = @"@@ -0,0 +1 @@
-+text
-";
- Assert.AreEqual (difftext, Repo.GenerateDiff (LocalPath + "testfile", Repo.GetVersionInfo (LocalPath + "testfile", VersionInfoQueryFlags.IgnoreCache)).Content.Replace ("\n", "\r\n"));
- }
-
- [Test]
- [Platform (Exclude = "Win")]
- public override void UpdateIsDone ()
- {
- base.UpdateIsDone ();
- }
-
- [Test]
- [Ignore ("Not implemented in GitRepository.")]
- public override void LocksEntities ()
- {
- base.LocksEntities ();
- }
-
- [Test]
- [Ignore ("Not implemented in GitRepository.")]
- public override void UnlocksEntities ()
- {
- base.UnlocksEntities ();
- }
-
- [Test]
- [Ignore ("This test is failing because the file is showing up as Unversioned, not ScheduledForDelete")]
- public override void DeletesFile ()
- {
- base.DeletesFile ();
- }
-
- [Test]
- [Ignore ("Apparently, we have issues with this")]
- public override void DeletesDirectory ()
- {
- base.DeletesDirectory ();
- }
-
- [Test]
- [Ignore ("NGit sees added directories as unversioned on Unix.")]
- public override void MovesFile ()
- {
- base.MovesFile ();
- }
-
- [Test]
- [Ignore ("NGit sees added directories as unversioned.")]
- public override void MovesDirectory ()
- {
- base.MovesDirectory ();
- }
-
- protected override Revision GetHeadRevision ()
- {
- var repo2 = (GitRepository)Repo;
- var rw = new RevWalk (repo2.RootRepository);
- ObjectId headId = repo2.RootRepository.Resolve (Constants.HEAD);
- if (headId == null)
- return null;
-
- RevCommit commit = rw.ParseCommit (headId);
- var rev = new GitRevision (Repo, repo2.RootRepository, commit.Id.Name);
- rev.Commit = commit;
- return rev;
- }
-
- protected override void PostCommit (Repository repo)
- {
- var repo2 = (GitRepository)repo;
- repo2.Push (new MonoDevelop.Core.ProgressMonitor (), repo2.GetCurrentRemote (), repo2.GetCurrentBranch ());
- }
-
- protected override void BlameExtraInternals (Annotation [] annotations)
- {
- // TODO: Fix this for bots.
-// for (int i = 0; i < 2; i++) {
-// Assert.IsTrue (annotations [i].HasEmail);
-// Assert.AreEqual (Author, annotations [i].Author);
-// Assert.AreEqual (String.Format ("<{0}>", Email), annotations [i].Email);
-// }
- Assert.IsTrue (annotations [2].HasDate);
- }
-
- [Test]
- [Ignore ("this is a new test which doesn't pass on Mac yet")]
- public void TestGitStash ()
- {
- var repo2 = (GitRepository)Repo;
- AddFile ("file2", "nothing", true, true);
- AddFile ("file1", "text", true, false);
- repo2.GetStashes ().Create (new NullProgressMonitor ());
- Assert.IsTrue (!File.Exists (LocalPath + "file1"), "Stash creation failure");
- repo2.GetStashes ().Pop (new NullProgressMonitor ());
-
- VersionInfo vi = repo2.GetVersionInfo (LocalPath + "file1", VersionInfoQueryFlags.IgnoreCache);
- Assert.AreEqual (VersionStatus.ScheduledAdd, vi.Status & VersionStatus.ScheduledAdd, "Stash pop failure");
- }
-
- [Test]
- [Ignore ("this is a new test which doesn't pass on Mac yet")]
- public void TestGitBranchCreation ()
- {
- var repo2 = (GitRepository)Repo;
-
- AddFile ("file1", "text", true, true);
- repo2.CreateBranch ("branch1", null);
-
- repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitor (), "branch1");
- Assert.AreEqual ("branch1", repo2.GetCurrentBranch ());
- Assert.IsTrue (File.Exists (LocalPath + "file1"), "Branch not inheriting from current.");
-
- AddFile ("file2", "text", true, false);
- repo2.CreateBranch ("branch2", null);
- repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitor (), "branch2");
- Assert.IsTrue (!File.Exists (LocalPath + "file2"), "Uncommitted changes were not stashed");
- repo2.GetStashes ().Pop (new NullProgressMonitor ());
-
- Assert.IsTrue (File.Exists (LocalPath + "file2"), "Uncommitted changes were not stashed correctly");
-
- repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitor (), "master");
- repo2.RemoveBranch ("branch1");
- Assert.IsFalse (repo2.GetBranches ().Any (b => b.Name == "branch1"), "Failed to delete branch");
-
- repo2.RenameBranch ("branch2", "branch3");
- Assert.IsTrue (repo2.GetBranches ().Any (b => b.Name == "branch3") && repo2.GetBranches ().All (b => b.Name != "branch2"), "Failed to rename branch");
-
- // TODO: Add CreateBranchFromCommit tests.
- }
-
- [Test]
- [Ignore ("this is a new test which doesn't pass on Mac yet")]
- public void TestGitSyncBranches ()
- {
- var repo2 = (GitRepository)Repo;
- AddFile ("file1", "text", true, true);
- PostCommit (repo2);
-
- repo2.CreateBranch ("branch3", null);
- repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitor (), "branch3");
- AddFile ("file2", "asdf", true, true);
- repo2.Push (new MonoDevelop.Core.ProgressMonitor (), "origin", "branch3");
-
- repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitor (), "master");
-
- repo2.CreateBranch ("branch4", "origin/branch3");
- repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitor (), "branch4");
- Assert.IsTrue (File.Exists (LocalPath + "file2"), "Tracking remote is not grabbing correct commits");
- }
-
- [Test]
- public void TestPushChangeset ()
- {
- var repo2 = (GitRepository)Repo;
- AddFile ("file", "meh", true, true);
- PostCommit (repo2);
-
- AddFile ("file1", "text", true, true);
- AddFile ("file2", "text2", true, true);
-
- ChangeSet diff = repo2.GetPushChangeSet ("origin", "master");
- Assert.AreEqual (2, diff.Items.Count ());
-
- ChangeSetItem item = diff.GetFileItem (LocalPath + "file1");
- Assert.IsNotNull (item);
- Assert.AreEqual (VersionStatus.ScheduledAdd, item.Status & VersionStatus.ScheduledAdd);
-
- item = diff.GetFileItem (LocalPath + "file1");
- Assert.IsNotNull (item);
- Assert.AreEqual (VersionStatus.ScheduledAdd, item.Status & VersionStatus.ScheduledAdd);
- }
-
- [Test]
- [Ignore ("GetPushDiff content is always empty")]
- public void TestPushDiff ()
- {
- var repo2 = (GitRepository)Repo;
- AddFile ("file", "meh", true, true);
- PostCommit (repo2);
-
- AddFile ("file1", "text", true, true);
- AddFile ("file2", "text2", true, true);
-
- DiffInfo[] diff = repo2.GetPushDiff ("origin", "master");
- Assert.AreEqual (2, diff.Length);
-
- DiffInfo item = diff [0];
- Assert.IsNotNull (item);
- Assert.AreEqual ("file1", item.FileName.FileName);
- //Assert.AreEqual ("text", item.Content);
-
- item = diff [1];
- Assert.IsNotNull (item);
- Assert.AreEqual ("file2", item.FileName.FileName);
- //Assert.AreEqual ("text2", item.Content);
- }
-
- protected override void TestValidUrl ()
- {
- var repo2 = (GitRepository)Repo;
- Assert.IsTrue (repo2.IsUrlValid ("git@github.com:mono/monodevelop"));
- Assert.IsTrue (repo2.IsUrlValid ("git://github.com:80/mono/monodevelop.git"));
- Assert.IsTrue (repo2.IsUrlValid ("ssh://user@host.com:80/mono/monodevelop.git"));
- Assert.IsTrue (repo2.IsUrlValid ("http://github.com:80/mono/monodevelop.git"));
- Assert.IsTrue (repo2.IsUrlValid ("https://github.com:80/mono/monodevelop.git"));
- Assert.IsTrue (repo2.IsUrlValid ("ftp://github.com:80/mono/monodevelop.git"));
- Assert.IsTrue (repo2.IsUrlValid ("ftps://github.com:80/mono/monodevelop.git"));
- Assert.IsTrue (repo2.IsUrlValid ("file:///mono/monodevelop.git"));
- Assert.IsTrue (repo2.IsUrlValid ("rsync://github.com/mono/monodevelpo.git"));
- }
-
- [Test]
- public void TestRemote ()
- {
- var repo2 = (GitRepository)Repo;
-
- Assert.AreEqual ("origin", repo2.GetCurrentRemote ());
-
- AddFile ("file1", "text", true, true);
- PostCommit (repo2);
- repo2.CreateBranch ("branch1", null);
- repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitor (), "branch1");
- AddFile ("file2", "text", true, true);
- PostCommit (repo2);
- Assert.AreEqual (2, repo2.GetBranches ().Count ());
- Assert.AreEqual (1, repo2.GetRemotes ().Count ());
-
- repo2.RenameRemote ("origin", "other");
- Assert.AreEqual ("other", repo2.GetCurrentRemote ());
-
- repo2.RemoveRemote ("other");
- Assert.IsFalse (repo2.GetRemotes ().Any ());
- }
-
- [Test]
- [Ignore ("this is a new test which doesn't pass on Mac yet")]
- public void TestIsMerged ()
- {
- var repo2 = (GitRepository)Repo;
- AddFile ("file1", "text", true, true);
-
- Assert.IsTrue (repo2.IsBranchMerged ("master"));
-
- repo2.CreateBranch ("branch1", null);
- repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitor (), "branch1");
- AddFile ("file2", "text", true, true);
-
- repo2.SwitchToBranch (new MonoDevelop.Core.ProgressMonitor (), "master");
- Assert.IsFalse (repo2.IsBranchMerged ("branch1"));
- repo2.Merge ("branch1", GitUpdateOptions.NormalUpdate, new MonoDevelop.Core.ProgressMonitor ());
- Assert.IsTrue (repo2.IsBranchMerged ("branch1"));
- }
-
- [Test]
- public void TestTags ()
- {
- var repo2 = (GitRepository)Repo;
- AddFile ("file1", "text", true, true);
- repo2.AddTag ("tag1", GetHeadRevision (), "my-tag");
- Assert.AreEqual (1, repo2.GetTags ().Count ());
- Assert.AreEqual ("tag1", repo2.GetTags ().First ());
- repo2.RemoveTag ("tag1");
- Assert.AreEqual (0, repo2.GetTags ().Count ());
- }
-
- // TODO: Test rebase and merge - This is broken on Windows
-
- protected override Repository GetRepo (string path, string url)
- {
- return new GitRepository (VersionControlService.GetVersionControlSystems ().First (id => id.Name == "Git"), path, url);
- }
-
- // This test is for a memory usage improvement on status.
- [Test]
- public void TestSameGitRevision ()
- {
- // Test that we have the same Revision on subsequent calls when HEAD doesn't change.
- AddFile ("file1", null, true, true);
- var info1 = Repo.GetVersionInfo (LocalPath + "file1", VersionInfoQueryFlags.IgnoreCache);
- var info2 = Repo.GetVersionInfo (LocalPath + "file1", VersionInfoQueryFlags.IgnoreCache);
- Assert.IsTrue (object.ReferenceEquals (info1.Revision, info2.Revision));
-
- // Test that we have the same Revision between two files on a HEAD bump.
- AddFile ("file2", null, true, true);
- var infos = Repo.GetVersionInfo (
- new FilePath[] { LocalPath + "file1", LocalPath + "file2" },
- VersionInfoQueryFlags.IgnoreCache
- ).ToArray ();
- Assert.IsTrue (object.ReferenceEquals (infos [0].Revision, infos [1].Revision));
-
- // Test that the new Revision and the old one are different instances.
- Assert.IsFalse (object.ReferenceEquals (info1.Revision, infos [0].Revision));
-
- // Write the first test so it also covers directories.
- AddDirectory ("meh", true, false);
- AddFile ("meh/file3", null, true, true);
- var info3 = Repo.GetVersionInfo (LocalPath + "meh", VersionInfoQueryFlags.IgnoreCache);
- var info4 = Repo.GetVersionInfo (LocalPath + "meh", VersionInfoQueryFlags.IgnoreCache);
- Assert.IsTrue (object.ReferenceEquals (info3.Revision, info4.Revision));
- }
- }
-}
-
+// +// RepositoryTests.cs +// +// Author: +// Therzok <teromario@yahoo.com> +// +// Copyright (c) 2013 Xamarin Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using MonoDevelop.Core; +using MonoDevelop.Core.ProgressMonitoring; +using MonoDevelop.VersionControl; +using MonoDevelop.VersionControl.Git; +using MonoDevelop.VersionControl.Tests; +using NUnit.Framework; +using System.IO; +using System.Linq; +using System; + +namespace MonoDevelop.VersionControl.Git.Tests +{ + [TestFixture] + sealed class BaseGitUtilsTest : BaseRepoUtilsTest + { + [SetUp] + public override void Setup () + { + // Generate directories and a svn util. + RemotePath = new FilePath (FileService.CreateTempDirectory () + Path.DirectorySeparatorChar); + LocalPath = new FilePath (FileService.CreateTempDirectory () + Path.DirectorySeparatorChar); + Directory.CreateDirectory (RemotePath.FullPath + "repo.git"); + RemoteUrl = "file://" + (Platform.IsWindows ? "/" : "") + RemotePath.FullPath + "repo.git"; + + LibGit2Sharp.Repository.Init (RemotePath.FullPath + "repo.git", true); + + // Check out the repository. + Checkout (LocalPath, RemoteUrl); + Repo = GetRepo (LocalPath, RemoteUrl); + ModifyPath (Repo, ref LocalPath); + DotDir = ".git"; + } + + protected override NUnit.Framework.Constraints.IResolveConstraint IsCorrectType () + { + return Is.InstanceOf<GitRepository> (); + } + + protected override int RepoItemsCount { + get { return 1; } + } + + protected override int RepoItemsCountRecursive { + get { return 10; } + } + + protected override void TestDiff () + { + string difftext = @"--- a/testfile ++++ b/testfile +@@ -0,0 +1 @@ ++text +\ No newline at end of file +"; + if (Platform.IsWindows) + difftext = difftext.Replace ("\r\n", "\n"); + Assert.AreEqual (difftext, Repo.GenerateDiff (LocalPath + "testfile", Repo.GetVersionInfo (LocalPath + "testfile", VersionInfoQueryFlags.IgnoreCache)).Content); + } + + protected override void ModifyPath (Repository repo, ref FilePath old) + { + var repo2 = (GitRepository)repo; + old = repo2.RootRepository.Info.WorkingDirectory; + repo2.RootRepository.Config.Set<string> ("user.name", Author); + repo2.RootRepository.Config.Set<string> ("user.email", Email); + } + + [Test] + [Ignore ("Not implemented in GitRepository.")] + public override void LocksEntities () + { + base.LocksEntities (); + } + + [Test] + [Ignore ("Not implemented in GitRepository.")] + public override void UnlocksEntities () + { + base.UnlocksEntities (); + } + + [Test] + [Ignore ("NGit sees added directories as unversioned.")] + public override void MovesDirectory () + { + base.MovesDirectory (); + } + + protected override Revision GetHeadRevision () + { + var repo2 = (GitRepository)Repo; + return new GitRevision (Repo, repo2.RootRepository, repo2.RootRepository.Head.Tip); + } + + protected override void PostCommit (Repository repo) + { + var repo2 = (GitRepository)repo; + repo2.Push (new NullProgressMonitor (), repo2.GetCurrentRemote (), repo2.GetCurrentBranch ()); + } + + protected override void BlameExtraInternals (Annotation [] annotations) + { + for (int i = 0; i < 2; i++) { + Assert.IsTrue (annotations [i].HasEmail); + Assert.AreEqual (Author, annotations [i].Author); + Assert.AreEqual (String.Format ("<{0}>", Email), annotations [i].Email); + } + Assert.IsTrue (annotations [2].HasDate); + } + + [Test] + public void TestGitStash () + { + LibGit2Sharp.Stash stash; + var repo2 = (GitRepository)Repo; + AddFile ("file2", "nothing", true, true); + AddFile ("file1", "text", true, false); + AddFile ("file3", "unstaged", false, false); + AddFile ("file4", "noconflict", true, false); + repo2.TryCreateStash (new NullProgressMonitor (), "meh", out stash); + Assert.IsTrue (!File.Exists (LocalPath + "file1"), "Stash creation failure"); + AddFile ("file4", "conflict", true, true); + repo2.PopStash (new NullProgressMonitor (), 0); + + VersionInfo vi = repo2.GetVersionInfo (LocalPath + "file1", VersionInfoQueryFlags.IgnoreCache); + Assert.IsTrue (File.Exists (LocalPath + "file1"), "Stash pop staged failure"); + Assert.AreEqual (VersionStatus.ScheduledAdd, vi.Status & VersionStatus.ScheduledAdd, "Stash pop failure"); + + vi = repo2.GetVersionInfo (LocalPath + "file3", VersionInfoQueryFlags.IgnoreCache); + Assert.IsTrue (File.Exists (LocalPath + "file3"), "Stash pop untracked failure"); + Assert.AreEqual (VersionStatus.Unversioned, vi.Status & VersionStatus.Unversioned, "Stash pop failure"); + + vi = repo2.GetVersionInfo (LocalPath + "file4", VersionInfoQueryFlags.IgnoreCache); + Assert.IsTrue (File.Exists (LocalPath + "file4"), "Stash pop conflict failure"); + Assert.AreEqual (VersionStatus.Conflicted, vi.Status & VersionStatus.Conflicted, "Stash pop failure"); + } + + [Test] + public void TestStashNoExtraCommit () + { + LibGit2Sharp.Stash stash; + var repo2 = (GitRepository)Repo; + AddFile ("file1", null, true, true); + AddFile ("file2", null, true, false); + AddFile ("file3", null, false, false); + + int commitCount = repo2.GetHistory (repo2.RootPath, null).Length; + repo2.TryCreateStash (new NullProgressMonitor (), "stash1", out stash); + repo2.PopStash (new NullProgressMonitor (), 0); + Assert.AreEqual (commitCount, repo2.GetHistory (repo2.RootPath, null).Length, "stash1 added extra commit."); + + repo2.TryCreateStash (new NullProgressMonitor (), "stash2", out stash); + + AddFile ("file4", null, true, true); + commitCount = repo2.GetHistory (repo2.RootPath, null).Length; + + repo2.PopStash (new NullProgressMonitor (), 0); + Assert.AreEqual (commitCount, repo2.GetHistory (repo2.RootPath, null).Length, "stash2 added extra commit."); + } + + static string GetStashMessageForBranch (string branch) + { + return string.Format ("On {0}: __MD_{0}\n\n", branch); + } + [Test] + public void TestGitBranchCreation () + { + var repo2 = (GitRepository)Repo; + + AddFile ("file1", "text", true, true); + repo2.CreateBranch ("branch1", null); + + repo2.SwitchToBranch (new NullProgressMonitor (), "branch1"); + // Nothing could be stashed for master. Branch1 should be popped in any case if it exists. + Assert.IsFalse (repo2.GetStashes ().Any (s => s.Message == GetStashMessageForBranch ("master"))); + Assert.IsFalse (repo2.GetStashes ().Any (s => s.Message == GetStashMessageForBranch ("branch1"))); + + Assert.AreEqual ("branch1", repo2.GetCurrentBranch ()); + Assert.IsTrue (File.Exists (LocalPath + "file1"), "Branch not inheriting from current."); + + AddFile ("file2", "text", true, false); + repo2.CreateBranch ("branch2", null); + + repo2.SwitchToBranch (new NullProgressMonitor (), "branch2"); + // Branch1 has a stash created and assert clean workdir. Branch2 should be popped in any case. + Assert.IsTrue (repo2.GetStashes ().Any (s => s.Message == GetStashMessageForBranch ("branch1"))); + Assert.IsFalse (repo2.GetStashes ().Any (s => s.Message == GetStashMessageForBranch ("branch2"))); + Assert.IsTrue (!File.Exists (LocalPath + "file2"), "Uncommitted changes were not stashed"); + + AddFile ("file2", "text", true, false); + repo2.SwitchToBranch (new NullProgressMonitor (), "branch1"); + // Branch2 has a stash created. Branch1 should be popped with file2 reinstated. + Assert.True (repo2.GetStashes ().Any (s => s.Message == GetStashMessageForBranch ("branch2"))); + Assert.IsFalse (repo2.GetStashes ().Any (s => s.Message == GetStashMessageForBranch ("branch1"))); + Assert.IsTrue (File.Exists (LocalPath + "file2"), "Uncommitted changes were not stashed correctly"); + + repo2.SwitchToBranch (new NullProgressMonitor (), "master"); + repo2.RemoveBranch ("branch1"); + Assert.IsFalse (repo2.GetBranches ().Any (b => b.Name == "branch1"), "Failed to delete branch"); + + repo2.RenameBranch ("branch2", "branch3"); + Assert.IsTrue (repo2.GetBranches ().Any (b => b.Name == "branch3") && repo2.GetBranches ().All (b => b.Name != "branch2"), "Failed to rename branch"); + + // TODO: Add CreateBranchFromCommit tests. + } + + [Test] + [Ignore ("this is a new test which doesn't pass on Mac yet")] + public void TestGitSyncBranches () + { + var repo2 = (GitRepository)Repo; + AddFile ("file1", "text", true, true); + PostCommit (repo2); + + repo2.CreateBranch ("branch3", null); + repo2.SwitchToBranch (new NullProgressMonitor (), "branch3"); + AddFile ("file2", "asdf", true, true); + repo2.Push (new NullProgressMonitor (), "origin", "branch3"); + + repo2.SwitchToBranch (new NullProgressMonitor (), "master"); + + repo2.CreateBranch ("branch4", "origin/branch3"); + repo2.SwitchToBranch (new NullProgressMonitor (), "branch4"); + Assert.IsTrue (File.Exists (LocalPath + "file2"), "Tracking remote is not grabbing correct commits"); + } + + [Test] + public void TestPushChangeset () + { + var repo2 = (GitRepository)Repo; + AddFile ("file", "meh", true, true); + PostCommit (repo2); + + AddFile ("file1", "text", true, true); + AddFile ("file2", "text2", true, true); + + ChangeSet diff = repo2.GetPushChangeSet ("origin", "master"); + Assert.AreEqual (2, diff.Items.Count ()); + + ChangeSetItem item = diff.GetFileItem (LocalPath + "file1"); + Assert.IsNotNull (item); + Assert.AreEqual (VersionStatus.ScheduledAdd, item.Status & VersionStatus.ScheduledAdd); + + item = diff.GetFileItem (LocalPath + "file1"); + Assert.IsNotNull (item); + Assert.AreEqual (VersionStatus.ScheduledAdd, item.Status & VersionStatus.ScheduledAdd); + } + + [Test] + public void TestPushDiff () + { + var repo2 = (GitRepository)Repo; + AddFile ("file", "meh", true, true); + PostCommit (repo2); + + AddFile ("file1", "text", true, true); + AddFile ("file2", "text2", true, true); + + DiffInfo[] diff = repo2.GetPushDiff ("origin", "master"); + Assert.AreEqual (2, diff.Length); + + DiffInfo item = diff [0]; + Assert.IsNotNull (item); + Assert.AreEqual ("file1", item.FileName.FileName); + string text = @"diff --git a/file1 b/file1 +new file mode 100644 +index 0000000..f3a3485 +--- /dev/null ++++ b/file1 +@@ -0,0 +1 @@ ++text +\ No newline at end of file +"; + + if (Platform.IsWindows) + text = text.Replace ("\r\n", "\n"); + Assert.AreEqual (text, item.Content); + + item = diff [1]; + Assert.IsNotNull (item); + Assert.AreEqual ("file2", item.FileName.FileName); + text = @"diff --git a/file2 b/file2 +new file mode 100644 +index 0000000..009b64b +--- /dev/null ++++ b/file2 +@@ -0,0 +1 @@ ++text2 +\ No newline at end of file +"; + if (Platform.IsWindows) + text = text.Replace ("\r\n", "\n"); + Assert.AreEqual (text, item.Content); + } + + protected override void TestValidUrl () + { + var repo2 = (GitRepository)Repo; + Assert.IsTrue (repo2.IsUrlValid ("git@github.com:mono/monodevelop")); + Assert.IsTrue (repo2.IsUrlValid ("git://github.com:80/mono/monodevelop.git")); + Assert.IsTrue (repo2.IsUrlValid ("ssh://user@host.com:80/mono/monodevelop.git")); + Assert.IsTrue (repo2.IsUrlValid ("http://github.com:80/mono/monodevelop.git")); + Assert.IsTrue (repo2.IsUrlValid ("https://github.com:80/mono/monodevelop.git")); + //Assert.IsTrue (repo2.IsUrlValid ("ftp://github.com:80/mono/monodevelop.git")); + //Assert.IsTrue (repo2.IsUrlValid ("ftps://github.com:80/mono/monodevelop.git")); + Assert.IsTrue (repo2.IsUrlValid ("file:///mono/monodevelop.git")); + //Assert.IsTrue (repo2.IsUrlValid ("rsync://github.com/mono/monodevelpo.git")); + } + + [Test] + public void TestRemote () + { + var repo2 = (GitRepository)Repo; + + Assert.AreEqual ("origin", repo2.GetCurrentRemote ()); + + AddFile ("file1", "text", true, true); + PostCommit (repo2); + repo2.CreateBranch ("branch1", null); + repo2.SwitchToBranch (new NullProgressMonitor (), "branch1"); + AddFile ("file2", "text", true, true); + PostCommit (repo2); + Assert.AreEqual (2, repo2.GetBranches ().Count ()); + Assert.AreEqual (1, repo2.GetRemotes ().Count ()); + + repo2.RenameRemote ("origin", "other"); + Assert.AreEqual ("other", repo2.GetCurrentRemote ()); + + repo2.RemoveRemote ("other"); + Assert.IsFalse (repo2.GetRemotes ().Any ()); + } + + [Test] + public void TestIsMerged () + { + var repo2 = (GitRepository)Repo; + AddFile ("file1", "text", true, true); + + Assert.IsTrue (repo2.IsBranchMerged ("master")); + + repo2.CreateBranch ("branch1", null); + repo2.SwitchToBranch (new NullProgressMonitor (), "branch1"); + AddFile ("file2", "text", true, true); + + repo2.SwitchToBranch (new NullProgressMonitor (), "master"); + Assert.IsFalse (repo2.IsBranchMerged ("branch1")); + repo2.Merge ("branch1", GitUpdateOptions.NormalUpdate, new NullProgressMonitor ()); + Assert.IsTrue (repo2.IsBranchMerged ("branch1")); + } + + [Test] + public void TestTags () + { + var repo2 = (GitRepository)Repo; + AddFile ("file1", "text", true, true); + repo2.AddTag ("tag1", GetHeadRevision (), "my-tag"); + Assert.AreEqual (1, repo2.GetTags ().Count ()); + Assert.AreEqual ("tag1", repo2.GetTags ().First ()); + repo2.RemoveTag ("tag1"); + Assert.AreEqual (0, repo2.GetTags ().Count ()); + } + + // TODO: Test rebase and merge - This is broken on Windows + + protected override Repository GetRepo (string path, string url) + { + return new GitRepository (VersionControlService.GetVersionControlSystems ().First (id => id.Name == "Git"), path, url); + } + + // This test is for a memory usage improvement on status. + [Test] + public void TestSameGitRevision () + { + // Test that we have the same Revision on subsequent calls when HEAD doesn't change. + AddFile ("file1", null, true, true); + var info1 = Repo.GetVersionInfo (LocalPath + "file1", VersionInfoQueryFlags.IgnoreCache); + var info2 = Repo.GetVersionInfo (LocalPath + "file1", VersionInfoQueryFlags.IgnoreCache); + Assert.IsTrue (object.ReferenceEquals (info1.Revision, info2.Revision)); + + // Test that we have the same Revision between two files on a HEAD bump. + AddFile ("file2", null, true, true); + var infos = Repo.GetVersionInfo ( + new FilePath[] { LocalPath + "file1", LocalPath + "file2" }, + VersionInfoQueryFlags.IgnoreCache + ).ToArray (); + Assert.IsTrue (object.ReferenceEquals (infos [0].Revision, infos [1].Revision)); + + // Test that the new Revision and the old one are different instances. + Assert.IsFalse (object.ReferenceEquals (info1.Revision, infos [0].Revision)); + + // Write the first test so it also covers directories. + AddDirectory ("meh", true, false); + AddFile ("meh/file3", null, true, true); + var info3 = Repo.GetVersionInfo (LocalPath + "meh", VersionInfoQueryFlags.IgnoreCache); + var info4 = Repo.GetVersionInfo (LocalPath + "meh", VersionInfoQueryFlags.IgnoreCache); + Assert.IsTrue (object.ReferenceEquals (info3.Revision, info4.Revision)); + } + + [Test] + // Tests bug #23274 + public void DeleteWithStagedChanges () + { + string added = LocalPath.Combine ("testfile"); + AddFile ("testfile", "test", true, true); + + // Test with VCS Remove. + File.WriteAllText ("testfile", "t"); + Repo.Add (added, false, new NullProgressMonitor ()); + Repo.DeleteFile (added, false, new NullProgressMonitor (), true); + Assert.AreEqual (VersionStatus.Versioned | VersionStatus.ScheduledDelete, Repo.GetVersionInfo (added, VersionInfoQueryFlags.IgnoreCache).Status); + + // Reset state. + Repo.Revert (added, false, new NullProgressMonitor ()); + + // Test with Project Remove. + File.WriteAllText ("testfile", "t"); + Repo.Add (added, false, new NullProgressMonitor ()); + Repo.DeleteFile (added, false, new NullProgressMonitor (), false); + Assert.AreEqual (VersionStatus.Versioned | VersionStatus.ScheduledDelete, Repo.GetVersionInfo (added, VersionInfoQueryFlags.IgnoreCache).Status); + } + } +} diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseRepositoryTests.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseRepositoryTests.cs index 648cc45fdb..1a64b3a6fa 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseRepositoryTests.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseRepositoryTests.cs @@ -35,7 +35,7 @@ using System.Collections.Generic; namespace MonoDevelop.VersionControl.Tests { [TestFixture] - abstract class BaseRepoUtilsTest + public abstract class BaseRepoUtilsTest { // [Git] Set user and email. protected const string Author = "author"; @@ -56,6 +56,10 @@ namespace MonoDevelop.VersionControl.Tests [TearDown] public virtual void TearDown () { + if (Repo != null) { + Repo.Dispose (); + Repo = null; + } DeleteDirectory (RemotePath); DeleteDirectory (LocalPath); AddedItems.Clear (); @@ -183,7 +187,7 @@ namespace MonoDevelop.VersionControl.Tests // Old cache. vis = Repo.GetDirectoryVersionInfo (LocalPath, false, false); - Assert.AreEqual (1 + RepoItemsCount, vis.Length); + Assert.AreEqual (1 + RepoItemsCount, vis.Length, "Old DirectoryVersionInfo."); // Query. Repo.ClearCachedVersionInfo (LocalPath); @@ -192,12 +196,12 @@ namespace MonoDevelop.VersionControl.Tests // Cached. vis = Repo.GetDirectoryVersionInfo (LocalPath, false, false); - Assert.AreEqual (2 + RepoItemsCount, vis.Length); + Assert.AreEqual (2 + RepoItemsCount, vis.Length, "New DirectoryVersionInfo."); // Wait for result. AddFile ("testfile3", null, true, false); vis = Repo.GetDirectoryVersionInfo (LocalPath, false, true); - Assert.AreEqual (4 + RepoItemsCountRecursive, vis.Length); + Assert.AreEqual (4 + RepoItemsCountRecursive, vis.Length, "Recursive DirectoryVersionInfo."); } [Test] @@ -240,11 +244,12 @@ namespace MonoDevelop.VersionControl.Tests FilePath second = new FilePath (FileService.CreateTempDirectory () + Path.DirectorySeparatorChar); Checkout (second, RemoteUrl); Repo2 = GetRepo (second, RemoteUrl); + ModifyPath (Repo2, ref second); string added = second + "testfile2"; File.Create (added).Close (); Repo2.Add (added, false, new ProgressMonitor ()); - ChangeSet changes = Repo.CreateChangeSet (Repo.RootPath); - changes.AddFile (Repo.GetVersionInfo (added, VersionInfoQueryFlags.IgnoreCache)); + ChangeSet changes = Repo2.CreateChangeSet (Repo2.RootPath); + changes.AddFile (Repo2.GetVersionInfo (added, VersionInfoQueryFlags.IgnoreCache)); changes.GlobalComment = "test2"; Repo2.Commit (changes, new ProgressMonitor ()); @@ -253,9 +258,14 @@ namespace MonoDevelop.VersionControl.Tests Repo.Update (Repo.RootPath, true, new ProgressMonitor ()); Assert.True (File.Exists (LocalPath + "testfile2")); + Repo2.Dispose (); DeleteDirectory (second); } + protected virtual void ModifyPath (Repository repo, ref FilePath old) + { + } + [Test] // Tests Repository.GetHistory. public void LogIsProper () @@ -273,7 +283,7 @@ namespace MonoDevelop.VersionControl.Tests public void DiffIsProper () { AddFile ("testfile", null, true, true); - File.AppendAllText (LocalPath + "testfile", "text" + Environment.NewLine); + File.AppendAllText (LocalPath + "testfile", "text"); TestDiff (); } @@ -301,7 +311,7 @@ namespace MonoDevelop.VersionControl.Tests AddFile ("testfile", "text", true, true); // TODO: Extend and test each member and more types. foreach (var rev in Repo.GetRevisionChanges (GetHeadRevision ())) { - Assert.AreEqual (rev.Action, RevisionAction.Add); + Assert.AreEqual (RevisionAction.Add, rev.Action); } } @@ -366,13 +376,13 @@ namespace MonoDevelop.VersionControl.Tests // Tests Repository.MoveDirectory. public virtual void MovesDirectory () { - string srcDir = LocalPath + "test"; - string dstDir = LocalPath + "test2"; - string src = srcDir + Path.DirectorySeparatorChar + "testfile"; - string dst = dstDir + Path.DirectorySeparatorChar + "testfile"; + string srcDir = LocalPath.Combine ("test"); + string dstDir = LocalPath.Combine ("test2"); + string src = Path.Combine (srcDir, "testfile"); + string dst = Path.Combine (dstDir, "testfile"); AddDirectory ("test", true, false); - AddFile ("test" + Path.DirectorySeparatorChar + "testfile", null, true, true); + AddFile (Path.Combine ("test", "testfile"), null, true, true); Repo.MoveDirectory (srcDir, dstDir, false, new ProgressMonitor ()); VersionInfo srcVi = Repo.GetVersionInfo (src, VersionInfoQueryFlags.IgnoreCache); @@ -388,7 +398,7 @@ namespace MonoDevelop.VersionControl.Tests string added; string postFix = keepLocal ? "2" : ""; // Versioned file. - added = LocalPath + "testfile1" + postFix; + added = LocalPath.Combine ("testfile1") + postFix; AddFile ("testfile1" + postFix, null, true, true); Repo.DeleteFile (added, true, new ProgressMonitor (), keepLocal); vi = Repo.GetVersionInfo (added, VersionInfoQueryFlags.IgnoreCache); @@ -396,7 +406,7 @@ namespace MonoDevelop.VersionControl.Tests Assert.AreEqual (keepLocal, File.Exists (added)); // Just added file. - added = LocalPath + "testfile2" + postFix; + added = LocalPath.Combine ("testfile2") + postFix; AddFile ("testfile2" + postFix, null, true, false); Repo.DeleteFile (added, true, new ProgressMonitor (), keepLocal); vi = Repo.GetVersionInfo (added, VersionInfoQueryFlags.IgnoreCache); @@ -404,7 +414,7 @@ namespace MonoDevelop.VersionControl.Tests Assert.AreEqual (keepLocal, File.Exists (added)); // Non versioned file. - added = LocalPath + "testfile3" + postFix; + added = LocalPath.Combine ("testfile3") + postFix; AddFile ("testfile3" + postFix, null, false, false); Repo.DeleteFile (added, true, new ProgressMonitor (), keepLocal); vi = Repo.GetVersionInfo (added, VersionInfoQueryFlags.IgnoreCache); @@ -412,12 +422,12 @@ namespace MonoDevelop.VersionControl.Tests Assert.AreEqual (keepLocal, File.Exists (added)); } - [Test] + [TestCase(false)] + [TestCase(true)] // Tests Repository.DeleteFile. - public virtual void DeletesFile () + public virtual void DeletesFile (bool keepLocal) { - DeleteFileTestHelper (false); - DeleteFileTestHelper (true); + DeleteFileTestHelper (keepLocal); } void DeleteTestDirectoryHelper (bool keepLocal) @@ -428,10 +438,10 @@ namespace MonoDevelop.VersionControl.Tests string postFix = keepLocal ? "2" : ""; // Versioned directory. - addedDir = LocalPath + "test1" + postFix; - added = addedDir + Path.DirectorySeparatorChar + "testfile"; + addedDir = LocalPath.Combine ("test1") + postFix; + added = Path.Combine (addedDir, "testfile"); AddDirectory ("test1" + postFix, true, false); - AddFile ("test1" + postFix + Path.DirectorySeparatorChar + "testfile", null, true, true); + AddFile (Path.Combine ("test1" + postFix, "testfile"), null, true, true); Repo.DeleteDirectory (addedDir, true, new ProgressMonitor (), keepLocal); vi = Repo.GetVersionInfo (added, VersionInfoQueryFlags.IgnoreCache); @@ -439,10 +449,10 @@ namespace MonoDevelop.VersionControl.Tests Assert.AreEqual (keepLocal, File.Exists (added)); // Just added directory. - addedDir = LocalPath + "test2" + postFix; - added = addedDir + Path.DirectorySeparatorChar + "testfile"; + addedDir = LocalPath.Combine ("test2") + postFix; + added = Path.Combine (addedDir, "testfile"); AddDirectory ("test2" + postFix, true, false); - AddFile ("test2" + postFix + Path.DirectorySeparatorChar + "testfile", null, true, false); + AddFile (Path.Combine ("test2" + postFix, "testfile"), null, true, false); Repo.DeleteDirectory (addedDir, true, new ProgressMonitor (), keepLocal); vi = Repo.GetVersionInfo (added, VersionInfoQueryFlags.IgnoreCache); @@ -450,10 +460,10 @@ namespace MonoDevelop.VersionControl.Tests Assert.AreEqual (keepLocal, File.Exists (added)); // Non versioned file. - addedDir = LocalPath + "test3" + postFix; - added = addedDir + Path.DirectorySeparatorChar + "testfile"; + addedDir = LocalPath.Combine ("test3") + postFix; + added = Path.Combine (addedDir, "testfile"); AddDirectory ("test3" + postFix, true, false); - AddFile ("test3" + postFix + Path.DirectorySeparatorChar + "testfile", null, false, false); + AddFile (Path.Combine ("test3" + postFix, "testfile"), null, false, false); Repo.DeleteDirectory (addedDir, true, new ProgressMonitor (), keepLocal); vi = Repo.GetVersionInfo (added, VersionInfoQueryFlags.IgnoreCache); @@ -524,18 +534,15 @@ namespace MonoDevelop.VersionControl.Tests } [Test] - [Ignore] - // TODO: Fix Subversion for Unix not returning the correct value. // TODO: Fix SvnSharp logic failing to generate correct URL. - // TODO: Fix Git TreeWalk failing. // Tests Repository.GetTextAtRevision. - public void CorrectTextAtRevision () + public virtual void CorrectTextAtRevision () { string added = LocalPath + "testfile"; AddFile ("testfile", "text1", true, true); File.AppendAllText (added, "text2"); CommitFile (added); - string text = Repo.GetTextAtRevision (LocalPath, GetHeadRevision ()); + string text = Repo.GetTextAtRevision (added, GetHeadRevision ()); Assert.AreEqual ("text1text2", text); } @@ -543,7 +550,7 @@ namespace MonoDevelop.VersionControl.Tests // Tests Repository.GetAnnotations. public void BlameIsCorrect () { - string added = LocalPath + "testfile"; + string added = LocalPath.Combine ("testfile"); // Initial commit. AddFile ("testfile", "blah" + Environment.NewLine, true, true); // Second commit. @@ -560,7 +567,7 @@ namespace MonoDevelop.VersionControl.Tests } BlameExtraInternals (annotations); - + Assert.False (annotations [2].HasEmail); Assert.IsNotNull (annotations [2].Author); Assert.IsNull (annotations [2].Email); @@ -570,6 +577,21 @@ namespace MonoDevelop.VersionControl.Tests protected abstract void BlameExtraInternals (Annotation [] annotations); + [Test] + // Tests bug #23275 + public void MoveAndMoveBack () + { + string added = LocalPath.Combine ("testfile"); + string dir = LocalPath.Combine ("testdir"); + string dirFile = Path.Combine (dir, "testfile"); + AddFile ("testfile", "test", true, true); + AddDirectory ("testdir", true, false); + Repo.MoveFile (added, dirFile, true, new ProgressMonitor ()); + Repo.MoveFile (dirFile, added, true, new ProgressMonitor ()); + + Assert.AreEqual (VersionStatus.Unversioned, Repo.GetVersionInfo (dirFile, VersionInfoQueryFlags.IgnoreCache).Status); + Assert.AreEqual (VersionStatus.Versioned, Repo.GetVersionInfo (added, VersionInfoQueryFlags.IgnoreCache).Status); + } #region Util protected void Checkout (string path, string url) @@ -656,4 +678,3 @@ namespace MonoDevelop.VersionControl.Tests #endregion } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/GitIntegrityTests.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/GitIntegrityTests.cs index 3c9e70fc9c..491a8ff3df 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/GitIntegrityTests.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/GitIntegrityTests.cs @@ -1,22 +1,22 @@ -// +// // GitUtilsTests.cs -// +// // Author: // IBBoard <dev@ibboard.co.uk> // Marius Ungureanu <marius.ungureanu@xamarin.com> -// +// // Copyright (c) 2011 IBBoard -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -24,14 +24,12 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -using System; +/*using System; using System.Linq; using NUnit.Framework; -using NGit.Storage.File; -using NGit.Revwalk; -using NGit; using System.IO; using System.Collections.Generic; +using LibGit2Sharp; namespace MonoDevelop.VersionControl.Git.Tests { @@ -39,21 +37,19 @@ namespace MonoDevelop.VersionControl.Git.Tests public class GitIntegrityTests { readonly string PROJECT_ROOT = "../../../"; - readonly Dictionary<string, RevCommit[]> blames = new Dictionary<string, RevCommit[]>(); - FileRepository repo; - RevWalk walker; - + readonly Dictionary<string, Commit[]> blames = new Dictionary<string, Commit[]>(); + LibGit2Sharp.Repository repo; + [SetUp] public void Setup() { var gitDir = new DirectoryInfo (PROJECT_ROOT + ".git"); - repo = new FileRepository (gitDir.FullName); - walker = new RevWalk (repo); + repo = new LibGit2Sharp.Repository (gitDir.FullName); } [Test] public void TestBlameLineCountWithMultipleCommits () { - RevCommit[] blameCommits = GetBlameForFixedFile ("c5f4319ee3e077436e3950c8a764959d50bf57c0"); + Commit[] blameCommits = GetBlameForFixedFile ("c5f4319ee3e077436e3950c8a764959d50bf57c0"); Assert.That (blameCommits.Length, Is.EqualTo (72)); } @@ -61,7 +57,7 @@ namespace MonoDevelop.VersionControl.Git.Tests [Ignore ("This fails with NGit, probably because the diff algorithm is different")] public void TestBlameRevisionsWithMultipleCommits () { - RevCommit[] blameCommits = GetBlameForFixedFile ("c5f4319ee3e077436e3950c8a764959d50bf57c0"); + Commit[] blameCommits = GetBlameForFixedFile ("c5f4319ee3e077436e3950c8a764959d50bf57c0"); var blames = new List<BlameFragment> (); blames.Add (new BlameFragment (1, 27, "b6e41ee2")); blames.Add (new BlameFragment (28, 1, "15ed2793")); @@ -83,17 +79,17 @@ namespace MonoDevelop.VersionControl.Git.Tests blames.Add(new BlameFragment(67, 1, "b6e41ee2")); blames.Add(new BlameFragment(68, 1, "c5f4319e")); blames.Add(new BlameFragment(69, 4, "b6e41ee2")); - + CompareBlames (blameCommits, blames); } - + [Test] [Ignore ("This fails with NGit, probably because the diff algorithm is different")] public void TestBlameRevisionsWithTwoCommits () { string commit1 = "b6e41ee2dd00e8744abc4835567e06667891b2cf"; string commit2 = "15ed279"; - RevCommit[] blameCommits = GetBlameForFixedFile (commit2); + Commit[] blameCommits = GetBlameForFixedFile (commit2); var blames = new List<BlameFragment> (); blames.Add (new BlameFragment (1, 27, commit1)); blames.Add (new BlameFragment (28, 1, commit2)); @@ -110,42 +106,43 @@ namespace MonoDevelop.VersionControl.Git.Tests blames.Add (new BlameFragment (64, 4, commit1)); CompareBlames (blameCommits, blames); } - + [Test] public void TestBlameLineCountWithTwoCommits () { - RevCommit[] blameCommits = GetBlameForFixedFile ("15ed279"); + Commit[] blameCommits = GetBlameForFixedFile ("15ed279"); Assert.That (blameCommits.Length, Is.EqualTo (67)); } - + [Test] public void TestBlameRevisionsWithOneCommit () { string commit = "b6e41ee2dd00e8744abc4835567e06667891b2cf"; - RevCommit[] blameCommits = GetBlameForFixedFile (commit); + Commit[] blameCommits = GetBlameForFixedFile (commit); var blames = new List<BlameFragment> (); - blames.Add (new BlameFragment (1, 56, commit)); + blames.Add (new BlameFragment (1, 56, commit)); CompareBlames (blameCommits, blames); } - + [Test] public void TestBlameLineCountWithOneCommit () { - RevCommit[] blameCommits = GetBlameForFixedFile ("b6e41ee2dd00e8744abc4835567e06667891b2cf"); + Commit[] blameCommits = GetBlameForFixedFile ("b6e41ee2dd00e8744abc4835567e06667891b2cf"); Assert.That (blameCommits.Length, Is.EqualTo (56)); } - + [Test] public void TestBlameLineCountWithNoCommits () { - RevCommit[] blameCommits = GetBlameForFixedFile ("39fe1158de8da8b82822e299958d35c51d493298"); + Commit[] blameCommits = GetBlameForFixedFile ("39fe1158de8da8b82822e299958d35c51d493298"); Assert.That (blameCommits, Is.Null); } - + [Test] + [Ignore] public void TestBlameForProjectDom () { - RevCommit[] blameCommits = GetBlameForFile ("6469602e3c0ba6953fd3ef0ae01d77abe1d9ab70", "main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Dom.Parser/ProjectDom.cs"); + Commit[] blameCommits = GetBlameForFile ("6469602e3c0ba6953fd3ef0ae01d77abe1d9ab70", "main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Dom.Parser/ProjectDom.cs"); var blames = new List<BlameFragment> (); blames.Add(new BlameFragment(1, 59, "3352c438")); blames.Add(new BlameFragment(60, 5, "85dfe8a5")); @@ -222,22 +219,23 @@ namespace MonoDevelop.VersionControl.Git.Tests blames.Add(new BlameFragment(1025, 43, "3352c438")); CompareBlames(blameCommits, blames); } - + [Test] public void GetCommitChangesAddedRemoved () { var commit = "9ed729ee"; - var changes = GitUtil.CompareCommits (repo, repo.Resolve (commit + "^"), repo.Resolve (commit)).ToArray (); + var com = repo.Lookup<Commit> (commit); + var changes = GitUtil.CompareCommits (repo, com.Parents.First (), com).ToArray (); - var add = changes.First (c => c.GetNewPath ().EndsWith ("DocumentLine.cs", StringComparison.Ordinal)); - var remove = changes.First (c => c.GetOldPath ().EndsWith ("LineSegment.cs", StringComparison.Ordinal)); + var add = changes.First (c => c.Path.EndsWith ("DocumentLine.cs", StringComparison.Ordinal)); + var remove = changes.First (c => c.OldPath.EndsWith ("LineSegment.cs", StringComparison.Ordinal)); - Assert.AreEqual (NGit.Diff.DiffEntry.ChangeType.ADD, add.GetChangeType (), "#1"); - Assert.AreEqual ("/dev/null", add.GetOldPath (), "#2"); - Assert.AreEqual (NGit.Diff.DiffEntry.ChangeType.DELETE, remove.GetChangeType (), "#3"); - Assert.AreEqual ("/dev/null", remove.GetNewPath (), "#4"); + Assert.AreEqual (ChangeKind.Renamed, add.Status, "#1"); + Assert.AreEqual ("main/src/core/Mono.Texteditor/Mono.TextEditor/Document/LineSegment.cs".Replace ('/', Path.DirectorySeparatorChar), add.OldPath, "#2"); + Assert.AreEqual (ChangeKind.Renamed, remove.Status, "#3"); + Assert.AreEqual ("main/src/core/Mono.Texteditor/Mono.TextEditor/Document/DocumentLine.cs".Replace ('/', Path.DirectorySeparatorChar), remove.Path, "#4"); } - + [Test] public void GetCommitChangesModifications () { @@ -255,51 +253,50 @@ namespace MonoDevelop.VersionControl.Git.Tests "TextEditor.cs", "TextViewMargin.cs", }; - - var changes = GitUtil.CompareCommits (repo, repo.Resolve (commit + "^"), repo.Resolve (commit)).ToArray (); + + var c = repo.Lookup<Commit> (commit); + var changes = GitUtil.CompareCommits (repo, c.Parents.First (), c).ToArray (); Assert.AreEqual (11, changes.Length, "#1"); - + foreach (var file in changedFiles) - Assert.IsTrue (changes.Any (f => f.GetNewPath ().EndsWith (".cs", StringComparison.Ordinal)), "#2." + file); + Assert.IsTrue (changes.Any (f => f.Path.EndsWith (".cs", StringComparison.Ordinal)), "#2." + file); } - - RevCommit[] GetBlameForFixedFile (string revision) + + Commit[] GetBlameForFixedFile (string revision) { string filePath = "main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitVersionControl.cs"; return GetBlameForFile (revision, filePath); } - - RevCommit[] GetBlameForFile (string revision, string filePath) + + Commit[] GetBlameForFile (string revision, string filePath) { - RevCommit[] blame; + Commit[] blame; string path = PROJECT_ROOT + filePath; string key = path + revision; blames.TryGetValue(key, out blame); - + if (blame == null) { - var git = new NGit.Api.Git (repo); - var commit = git.GetRepository ().Resolve (revision); - var result = git.Blame ().SetFilePath (filePath).SetStartCommit (commit).Call (); + var result = repo.Blame (filePath); if (result == null) return null; - blame = new RevCommit [result.GetResultContents ().Size ()]; - for (int i = 0; i < result.GetResultContents ().Size (); i ++) - blame [i] = result.GetSourceCommit (i); + blame = new Commit [result.Count ()]; + for (int i = 0; i < result.Count (); i ++) + blame [i] = result[i].FinalCommit; blames.Add(key, blame); } - + return blame; } - - static void CompareBlames (RevCommit[] blameCommits,List<BlameFragment> blames) + + static void CompareBlames (Commit[] blameCommits,List<BlameFragment> blames) { foreach (BlameFragment blame in blames) { int zeroBasedStartLine = blame.StartLine - 1; - + for (int i = 0; i < blame.LineCount; i++) { - Assert.That (blameCommits [zeroBasedStartLine + i].Id.Name, Is.StringStarting (blame.RevID), "Error at line {0}", blame.StartLine + i); + Assert.That (blameCommits [zeroBasedStartLine + i].Id.Sha, Is.StringStarting (blame.RevID), "Error at line {0}", blame.StartLine + i); } } } @@ -319,4 +316,4 @@ namespace MonoDevelop.VersionControl.Git.Tests } } } - +*/ diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/MonoDevelop.VersionControl.Git.Tests.csproj b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/MonoDevelop.VersionControl.Git.Tests.csproj index 55d73a7d98..2c3a486cc9 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/MonoDevelop.VersionControl.Git.Tests.csproj +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/MonoDevelop.VersionControl.Git.Tests.csproj @@ -23,6 +23,7 @@ <WarningLevel>4</WarningLevel> <ConsolePause>false</ConsolePause> <NoWarn>1591;1573</NoWarn> + <TreatWarningsAsErrors>true</TreatWarningsAsErrors> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <DebugType>pdbonly</DebugType> @@ -34,6 +35,39 @@ <DebugSymbols>true</DebugSymbols> <NoWarn>1591;1573</NoWarn> </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugMac|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\..\..\build\tests</OutputPath> + <DefineConstants>DEBUG</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <ConsolePause>false</ConsolePause> + <NoWarn>1591;1573</NoWarn> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugWin32|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\..\..\build\tests</OutputPath> + <DefineConstants>DEBUG</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <ConsolePause>false</ConsolePause> + <NoWarn>1591;1573</NoWarn> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugGnome|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\..\..\build\tests</OutputPath> + <DefineConstants>DEBUG</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <ConsolePause>false</ConsolePause> + <NoWarn>1591;1573</NoWarn> + </PropertyGroup> <ItemGroup> <Reference Include="System" /> </ItemGroup> @@ -59,27 +93,33 @@ <Name>MonoDevelop.VersionControl</Name> <Private>False</Private> </ProjectReference> - <ProjectReference Include="..\..\..\..\external\ngit\NGit\NGit.csproj"> - <Project>{E3BFF8B4-189C-496A-A817-7E8B31E22B91}</Project> - <Name>NGit</Name> - <Private>False</Private> - </ProjectReference> - <ProjectReference Include="..\..\..\..\external\ngit\NSch\NSch.csproj"> - <Project>{A19E6F3F-A25B-4B01-8922-CF0CC35C781D}</Project> - <Name>NSch</Name> - <Private>False</Private> - </ProjectReference> - <ProjectReference Include="..\..\..\..\external\ngit\Sharpen\Sharpen.csproj"> - <Project>{72944A6C-45FF-4EF8-B349-8C9CABF519D4}</Project> - <Name>Sharpen</Name> - </ProjectReference> - <ProjectReference Include="..\..\..\..\external\ngit\Sharpen.Unix\Sharpen.Unix.csproj"> - <Project>{849AE05D-0058-4A8C-A0E8-77DC6BB12E52}</Project> - <Name>Sharpen.Unix</Name> - </ProjectReference> <ProjectReference Include="..\..\..\..\external\guiunit\src\framework\GuiUnit_NET_4_5.csproj"> <Project>{D12F0F7B-8DE3-43EC-BA49-41052D065A9B}</Project> <Name>GuiUnit_NET_4_5</Name> </ProjectReference> + <ProjectReference Include="..\..\..\..\external\libgit2sharp\LibGit2Sharp\LibGit2Sharp.csproj"> + <Project>{EE6ED99F-CB12-4683-B055-D28FC7357A34}</Project> + <Name>LibGit2Sharp</Name> + </ProjectReference> </ItemGroup> + <Choose> + <When Condition=" '$(Configuration)' == 'DebugMac' "> + <ItemGroup> + <NativeBinaries Include="..\..\..\..\external\libgit-binary\mac\*.dylib" /> + </ItemGroup> + </When> + <When Condition=" '$(Configuration)' == 'DebugWin32' "> + <ItemGroup> + <NativeBinaries Include="..\..\..\..\external\libgit-binary\windows\*.*" /> + </ItemGroup> + </When> + <When Condition=" '$(Configuration)' == 'DebugGnome' "> + <ItemGroup> + <NativeBinaries Include="..\..\..\..\external\libgit2sharp\libgit2\build\*.*" /> + </ItemGroup> + </When> + </Choose> + <Target Name="AfterBuild"> + <Copy SourceFiles="@(NativeBinaries)" DestinationFolder="$(OutputPath)\" SkipUnchangedFiles="true" /> + </Target> </Project>
\ No newline at end of file diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git.addin.xml b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git.addin.xml index b367f69ac1..7cf11f11b9 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git.addin.xml +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git.addin.xml @@ -1,7 +1,7 @@ <ExtensionModel> <Runtime> - <Import assembly="NGit.dll"/> + <Import assembly="LibGit2Sharp.dll"/> <Import file="GitIgnore.txt" /> </Runtime> diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git.csproj b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git.csproj index e766b05886..0c9fcac0bb 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git.csproj +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git.csproj @@ -34,6 +34,43 @@ <NoWarn>1591;1573</NoWarn> <DocumentationFile>..\..\..\..\build\AddIns\VersionControl\MonoDevelop.VersionControl.Git.xml</DocumentationFile> </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugMac|AnyCPU' "> + <DebugSymbols>True</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>False</Optimize> + <OutputPath>..\..\..\..\build\AddIns\VersionControl</OutputPath> + <DefineConstants>DEBUG</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <ConsolePause>False</ConsolePause> + <NoWarn>1591;1573</NoWarn> + <DocumentationFile>..\..\..\..\build\AddIns\VersionControl\MonoDevelop.VersionControl.Git.xml</DocumentationFile> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugGnome|AnyCPU' "> + <DebugSymbols>True</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>False</Optimize> + <OutputPath>..\..\..\..\build\AddIns\VersionControl</OutputPath> + <DefineConstants>DEBUG</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <ConsolePause>False</ConsolePause> + <NoWarn>1591;1573</NoWarn> + <DocumentationFile>..\..\..\..\build\AddIns\VersionControl\MonoDevelop.VersionControl.Git.xml</DocumentationFile> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugWin32|AnyCPU' "> + <DebugSymbols>True</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>False</Optimize> + <OutputPath>..\..\..\..\build\AddIns\VersionControl</OutputPath> + <DefineConstants>DEBUG</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <ConsolePause>False</ConsolePause> + <DocumentationFile>..\..\..\..\build\AddIns\VersionControl\MonoDevelop.VersionControl.Git.xml</DocumentationFile> + <TreatWarningsAsErrors>true</TreatWarningsAsErrors> + <NoWarn>1591</NoWarn> + </PropertyGroup> <ItemGroup> <Reference Include="System" /> <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" /> @@ -81,10 +118,8 @@ <Compile Include="MonoDevelop.VersionControl.Git\GitCommitDialogExtensionWidget.cs" /> <Compile Include="gtk-gui\MonoDevelop.VersionControl.Git.GitCommitDialogExtensionWidget.cs" /> <Compile Include="MonoDevelop.VersionControl.Git\GitCommitDialogExtension.cs" /> - <Compile Include="MonoDevelop.VersionControl.Git\FilteredStatus.cs" /> <Compile Include="MonoDevelop.VersionControl.Git\UserGitConfigDialog.cs" /> <Compile Include="gtk-gui\MonoDevelop.VersionControl.Git.UserGitConfigDialog.cs" /> - <Compile Include="MonoDevelop.VersionControl.Git\MyersDiff.cs" /> <Compile Include="MonoDevelop.VersionControl.Git\GitSelectRevisionDialog.cs" /> <Compile Include="AddinInfo.cs" /> <Compile Include="MonoDevelop.VersionControl.Git\ProjectTemplateHandler.cs" /> @@ -110,22 +145,6 @@ <Name>MonoDevelop.VersionControl</Name> <Private>False</Private> </ProjectReference> - <ProjectReference Include="..\..\..\..\external\ngit\NGit\NGit.csproj"> - <Project>{E3BFF8B4-189C-496A-A817-7E8B31E22B91}</Project> - <Name>NGit</Name> - </ProjectReference> - <ProjectReference Include="..\..\..\..\external\ngit\NSch\NSch.csproj"> - <Project>{A19E6F3F-A25B-4B01-8922-CF0CC35C781D}</Project> - <Name>NSch</Name> - </ProjectReference> - <ProjectReference Include="..\..\..\..\external\ngit\Sharpen\Sharpen.csproj"> - <Project>{72944A6C-45FF-4EF8-B349-8C9CABF519D4}</Project> - <Name>Sharpen</Name> - </ProjectReference> - <ProjectReference Include="..\..\..\..\external\ngit\Sharpen.Unix\Sharpen.Unix.csproj"> - <Project>{849AE05D-0058-4A8C-A0E8-77DC6BB12E52}</Project> - <Name>Sharpen.Unix</Name> - </ProjectReference> <ProjectReference Include="..\..\..\..\external\xwt\Xwt\Xwt.csproj"> <Project>{92494904-35FA-4DC9-BDE9-3A3E87AC49D3}</Project> <Name>Xwt</Name> @@ -136,6 +155,15 @@ <Name>Mono.Addins</Name> <Private>False</Private> </ProjectReference> + <ProjectReference Include="..\..\..\..\external\libgit2sharp\LibGit2Sharp\LibGit2Sharp.csproj"> + <Project>{EE6ED99F-CB12-4683-B055-D28FC7357A34}</Project> + <Name>LibGit2Sharp</Name> + </ProjectReference> + <ProjectReference Include="..\..\..\..\external\nrefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj"> + <Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project> + <Name>ICSharpCode.NRefactory</Name> + <Private>False</Private> + </ProjectReference> </ItemGroup> <ItemGroup> <EmbeddedResource Include="MonoDevelop.VersionControl.Git.addin.xml"> @@ -153,4 +181,27 @@ </None> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> + <Choose> + <When Condition=" '$(Configuration)' == 'DebugMac' "> + <ItemGroup> + <NativeBinaries Include="..\..\..\..\external\libgit-binary\mac\*.dylib" /> + </ItemGroup> + </When> + <When Condition=" '$(Configuration)' == 'DebugWin32' "> + <ItemGroup> + <NativeBinaries Include="..\..\..\..\external\libgit-binary\windows\*.*" /> + </ItemGroup> + </When> + <When Condition=" '$(Configuration)' == 'DebugGnome' "> + <ItemGroup> + <NativeBinaries Include="..\..\..\..\external\libgit2sharp\libgit2\build\*.*" /> + </ItemGroup> + </When> + </Choose> + <Target Name="BeforeBuild"> + <Exec Command="bash build_libgit2.sh" Condition=" '$(Configuration)' == 'DebugGnome' " /> + </Target> + <Target Name="AfterBuild"> + <Copy SourceFiles="@(NativeBinaries)" DestinationFolder="$(OutputPath)\" SkipUnchangedFiles="true" /> + </Target> </Project>
\ No newline at end of file diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/Commands.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/Commands.cs index 4e5f7689af..1ca7238969 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/Commands.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/Commands.cs @@ -1,21 +1,21 @@ -// +// // Command.cs -// +// // Author: // Lluis Sanchez Gual <lluis@novell.com> -// +// // Copyright (c) 2010 Novell, Inc (http://www.novell.com) -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -31,6 +31,7 @@ using MonoDevelop.Projects; using System.Linq; using MonoDevelop.Ide.ProgressMonitoring; using System.Threading; +using LibGit2Sharp; using MonoDevelop.Core; namespace MonoDevelop.VersionControl.Git @@ -46,7 +47,7 @@ namespace MonoDevelop.VersionControl.Git StashPop, ManageStashes } - + class GitCommandHandler: CommandHandler { public GitRepository Repository { @@ -59,35 +60,49 @@ namespace MonoDevelop.VersionControl.Git return null; } } - - protected override void Update (CommandInfo info) + + protected GitRepository UpdateVisibility (CommandInfo info) { + var repo = Repository; info.Visible = Repository != null; + return repo; + } + + protected override void Update (CommandInfo info) + { + UpdateVisibility (info); } } - + class PushCommandHandler: GitCommandHandler { + protected override void Update (CommandInfo info) + { + var repo = UpdateVisibility (info); + if (repo != null) + info.Enabled = repo.GetCurrentRemote () != null; + } + protected override void Run () { GitService.Push (Repository); } } - + class SwitchToBranchHandler: GitCommandHandler { protected override void Run (object dataItem) { GitService.SwitchToBranch (Repository, (string)dataItem); } - + protected override void Update (CommandArrayInfo info) { var repo = Repository; if (repo == null) return; - WorkspaceObject wob = IdeApp.ProjectOperations.CurrentSelectedItem as WorkspaceObject; + var wob = IdeApp.ProjectOperations.CurrentSelectedItem as WorkspaceObject; if (wob == null) return; if (((wob is WorkspaceItem) && ((WorkspaceItem)wob).ParentWorkspace == null) || @@ -102,7 +117,7 @@ namespace MonoDevelop.VersionControl.Git } } } - + class ManageBranchesHandler: GitCommandHandler { protected override void Run () @@ -110,7 +125,7 @@ namespace MonoDevelop.VersionControl.Git GitService.ShowConfigurationDialog (Repository); } } - + class MergeBranchHandler: GitCommandHandler { protected override void Run () @@ -118,7 +133,7 @@ namespace MonoDevelop.VersionControl.Git GitService.ShowMergeDialog (Repository, false); } } - + class RebaseBranchHandler: GitCommandHandler { protected override void Run () @@ -126,22 +141,21 @@ namespace MonoDevelop.VersionControl.Git GitService.ShowMergeDialog (Repository, true); } } - + class StashHandler: GitCommandHandler { protected override void Run () { - var stashes = Repository.GetStashes (); - NewStashDialog dlg = new NewStashDialog (); + var dlg = new NewStashDialog (); try { if (MessageService.RunCustomDialog (dlg) == (int) Gtk.ResponseType.Ok) { string comment = dlg.Comment; - MessageDialogProgressMonitor monitor = new MessageDialogProgressMonitor (true, false, false, true); + var monitor = new MessageDialogProgressMonitor (true, false, false, true); var statusTracker = IdeApp.Workspace.GetFileStatusTracker (); ThreadPool.QueueUserWorkItem (delegate { try { - using (var gm = new GitMonitor (monitor)) - stashes.Create (gm, comment); + Stash stash; + Repository.TryCreateStash (monitor, comment, out stash); } catch (Exception ex) { MessageService.ShowError (GettextCatalog.GetString ("Stash operation failed"), ex); } @@ -156,20 +170,16 @@ namespace MonoDevelop.VersionControl.Git } } } - + class StashPopHandler: GitCommandHandler { protected override void Run () { - var stashes = Repository.GetStashes (); - MessageDialogProgressMonitor monitor = new MessageDialogProgressMonitor (true, false, false, true); + var monitor = new MessageDialogProgressMonitor (true, false, false, true); var statusTracker = IdeApp.Workspace.GetFileStatusTracker (); ThreadPool.QueueUserWorkItem (delegate { try { - NGit.Api.MergeCommandResult result; - using (var gm = new GitMonitor (monitor)) - result = stashes.Pop (gm); - GitService.ReportStashResult (monitor, result); + GitService.ReportStashResult (Repository.PopStash (monitor, 0)); } catch (Exception ex) { MessageService.ShowError (GettextCatalog.GetString ("Stash operation failed"), ex); } @@ -179,18 +189,15 @@ namespace MonoDevelop.VersionControl.Git } }); } - + protected override void Update (CommandInfo info) { - var repo = Repository; - if (repo != null) { - var s = repo.GetStashes (); - info.Enabled = s.Any (); - } else - info.Visible = false; + var repo = UpdateVisibility (info); + if (repo != null) + info.Enabled = repo.GetStashes ().Any (); } } - + class ManageStashesHandler: GitCommandHandler { protected override void Run () @@ -199,4 +206,3 @@ namespace MonoDevelop.VersionControl.Git } } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/ConflictResolutionDialog.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/ConflictResolutionDialog.cs index 37b24b7877..d1bd93460a 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/ConflictResolutionDialog.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/ConflictResolutionDialog.cs @@ -1,21 +1,21 @@ -// +// // ConflictResolutionDialog.cs -// +// // Author: // Lluis Sanchez Gual <lluis@novell.com> -// +// // Copyright (c) 2010 Novell, Inc (http://www.novell.com) -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -36,28 +36,27 @@ namespace MonoDevelop.VersionControl.Git this.Build (); HasSeparator = false; } - + public void Load (string file) { mergeWidget.Load (file); string msg = GettextCatalog.GetString ("A merge conflict has been detected in file <b>{0}</b>", System.IO.Path.GetFileName (file)); labelTop.Markup = msg; } - + public void Save (string file) { string enc = TextFile.GetFileEncoding (file); TextFile.WriteFile (file, mergeWidget.GetResultText (), enc); } } - + enum ConflictResult { Abort, Skip, Continue } - - -} + +} diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/CredentialsDialog.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/CredentialsDialog.cs index 22c936ef96..ac156c8eb4 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/CredentialsDialog.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/CredentialsDialog.cs @@ -1,21 +1,21 @@ -// +// // CredentialsDialog.cs -// +// // Author: // Lluis Sanchez Gual <lluis@novell.com> -// +// // Copyright (c) 2010 Novell, Inc (http://www.novell.com) -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -23,99 +23,78 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -using System.Linq; -using System.Collections.Generic; using Gtk; -using NGit.Transport; +using System; +using LibGit2Sharp; namespace MonoDevelop.VersionControl.Git { - partial class CredentialsDialog : Gtk.Dialog + partial class CredentialsDialog : Dialog { - readonly CredentialItem.YesNoType singleYesNoCred; - - public CredentialsDialog (URIish uri, IEnumerable<CredentialItem> credentials) + uint r; + public CredentialsDialog (string uri, SupportedCredentialTypes type, Credentials cred) { this.Build (); - - labelTop.Text = string.Format (labelTop.Text, uri.ToString ()); - - Gtk.Table table = new Gtk.Table (0, 0, false); + + labelTop.Text = string.Format (labelTop.Text, uri); + + var table = new Table (0, 0, false); table.ColumnSpacing = 6; vbox.PackStart (table, true, true, 0); - - uint r = 0; + Widget firstEditor = null; - foreach (CredentialItem c in credentials) { - Label lab = new Label (c.GetPromptText () + ":"); - lab.Xalign = 0; - table.Attach (lab, 0, 1, r, r + 1); - Table.TableChild tc = (Table.TableChild) table [lab]; - tc.XOptions = AttachOptions.Shrink; - - Widget editor = null; - - if (c is CredentialItem.YesNoType) { - CredentialItem.YesNoType cred = (CredentialItem.YesNoType) c; - if (credentials.Count (i => i is CredentialItem.YesNoType) == 1) { - singleYesNoCred = cred; - buttonOk.Hide (); - buttonYes.Show (); - buttonNo.Show (); - // Remove the last colon - lab.Text = lab.Text.Substring (0, lab.Text.Length - 1); - } - else { - CheckButton btn = new CheckButton (); - editor = btn; - btn.Toggled += delegate { - cred.SetValue (btn.Active); - }; - } - } - else if (c is CredentialItem.StringType || c is CredentialItem.CharArrayType) { - CredentialItem cred = c; - Entry e = new Entry (); - editor = e; - e.ActivatesDefault = true; - if (cred.IsValueSecure ()) - e.Visibility = false; - e.Changed += delegate { - if (cred is CredentialItem.StringType) - ((CredentialItem.StringType)cred).SetValue (e.Text); - else - ((CredentialItem.CharArrayType)cred).SetValue (e.Text.ToCharArray ()); - }; - - if (c is CredentialItem.Username) - e.Text = uri.GetUser () ?? ""; - } - if (editor != null) { - table.Attach (editor, 1, 2, r, r + 1); - tc = (Table.TableChild) table [lab]; - tc.XOptions = AttachOptions.Fill; - if (firstEditor == null) - firstEditor = editor; - } - - r++; + switch (type) { + case SupportedCredentialTypes.UsernamePassword: + upcred = (UsernamePasswordCredentials)cred; + firstEditor = CreateEntry (table, "Username:", false); + CreateEntry (table, "Password:", true); + break; + case SupportedCredentialTypes.Ssh: + sshcred = (SshUserKeyCredentials)cred; + firstEditor = CreateEntry (table, "Passphrase:", true); + break; } table.ShowAll (); Focus = firstEditor; Default = buttonOk; } - - protected virtual void OnButtonYesClicked (object sender, System.EventArgs e) - { - singleYesNoCred.SetValue (true); - Respond (ResponseType.Ok); - } - - protected virtual void OnButtonNoClicked (object sender, System.EventArgs e) + + Widget CreateEntry (Table table, string text, bool password) { - singleYesNoCred.SetValue (false); - Respond (ResponseType.Cancel); + var lab = new Label (text); + lab.Xalign = 0; + table.Attach (lab, 0, 1, r, r + 1); + var tc = (Table.TableChild)table [lab]; + tc.XOptions = AttachOptions.Shrink; + + var e = new Entry (); + Widget editor = e; + e.ActivatesDefault = true; + if (password) + e.Visibility = false; + + e.Changed += delegate { + if (password) { + if (upcred != null) + upcred.Password = e.Text ?? ""; + else + sshcred.Passphrase = e.Text ?? ""; + } else { + if (upcred != null) + upcred.Username = e.Text; + } + }; + + if (editor != null) { + table.Attach (editor, 1, 2, r, r + 1); + tc = (Table.TableChild)table [lab]; + tc.XOptions = AttachOptions.Fill; + } + r++; + return editor; } + + readonly UsernamePasswordCredentials upcred; + readonly SshUserKeyCredentials sshcred; } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/EditBranchDialog.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/EditBranchDialog.cs index ee9e6dfd39..96e6b9f035 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/EditBranchDialog.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/EditBranchDialog.cs @@ -1,21 +1,21 @@ -// +// // EditBranchDialog.cs -// +// // Author: // Lluis Sanchez Gual <lluis@novell.com> -// +// // Copyright (c) 2010 Novell, Inc (http://www.novell.com) -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -29,6 +29,7 @@ using Gtk; using MonoDevelop.Core; using MonoDevelop.Ide; using MonoDevelop.Components; +using LibGit2Sharp; namespace MonoDevelop.VersionControl.Git { @@ -38,13 +39,19 @@ namespace MonoDevelop.VersionControl.Git readonly string currentTracking; readonly string oldName; readonly GitRepository repo; - - public EditBranchDialog (GitRepository repo, Branch branch, bool isNew) + + public EditBranchDialog (GitRepository repo) : this(repo, string.Empty, string.Empty) + { + } + + public EditBranchDialog (GitRepository repo, string name, string tracking) { this.Build (); - this.repo = repo; - - comboStore = new ListStore (typeof(string), typeof(Xwt.Drawing.Image), typeof (string)); + this.repo = repo; + oldName = name; + currentTracking = tracking; + + comboStore = new ListStore (typeof(string), typeof(Xwt.Drawing.Image), typeof (string), typeof(string)); comboSources.Model = comboStore; var crp = new CellRendererImage (); comboSources.PackStart (crp, false); @@ -52,52 +59,44 @@ namespace MonoDevelop.VersionControl.Git var crt = new CellRendererText (); comboSources.PackStart (crt, true); comboSources.AddAttribute (crt, "text", 2); - - if (branch != null) { - if (!isNew) - oldName = branch.Name; - currentTracking = branch.Tracking; - entryName.Text = branch.Name; - checkTrack.Active = currentTracking != null; - } - + foreach (Branch b in repo.GetBranches ()) { - AddValues (b.Name, ImageService.GetIcon ("vc-branch", IconSize.Menu)); + AddValues (b.Name, ImageService.GetIcon ("vc-branch", IconSize.Menu), "refs/heads/"); } - - foreach (string t in repo.GetTags ()) - AddValues (t, ImageService.GetIcon ("vc-tag", IconSize.Menu)); - - foreach (RemoteSource r in repo.GetRemotes ()) { + + foreach (Remote r in repo.GetRemotes ()) { foreach (string b in repo.GetRemoteBranches (r.Name)) - AddValues (r.Name + "/" + b, ImageService.GetIcon ("vc-repository", IconSize.Menu)); + AddValues (r.Name + "/" + b, ImageService.GetIcon ("vc-repository", IconSize.Menu), "refs/remotes/"); } - + + entryName.Text = name; + checkTrack.Active = !string.IsNullOrEmpty (tracking); + UpdateStatus (); } - - void AddValues (string name, Xwt.Drawing.Image icon) + + void AddValues (string name, Xwt.Drawing.Image icon, string prefix) { - TreeIter it = comboStore.AppendValues (name, icon, name); + TreeIter it = comboStore.AppendValues (name, icon, name, prefix); if (name == currentTracking) comboSources.SetActiveIter (it); } - + public string TrackSource { get { if (checkTrack.Active) { TreeIter it; if (comboSources.GetActiveIter (out it)) - return (string) comboStore.GetValue (it, 0); + return (string)comboStore.GetValue (it, 3) + (string)comboStore.GetValue (it, 0); } return null; } } - + public string BranchName { get { return entryName.Text; } } - + void UpdateStatus () { comboSources.Sensitive = checkTrack.Active; @@ -106,7 +105,7 @@ namespace MonoDevelop.VersionControl.Git labelError.Markup = "<span color='red'>" + GettextCatalog.GetString ("A branch with this name already exists") + "</span>"; labelError.Show (); buttonOk.Sensitive = false; - } else if (!GitUtil.IsValidBranchName (entryName.Text)) { + } else if (!Reference.IsValidName ("refs/" + entryName.Text)) { labelError.Markup = "<span color='red'>" + GettextCatalog.GetString (@"A branch name can not: Start with '.' or end with '/' or '.lock' Contain a ' ', '..', '~', '^', ':', '\', '?', '['") + "</span>"; @@ -120,11 +119,10 @@ Contain a ' ', '..', '~', '^', ':', '\', '?', '['") + "</span>"; { UpdateStatus (); } - + protected virtual void OnEntryNameChanged (object sender, System.EventArgs e) { UpdateStatus (); } } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/EditRemoteDialog.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/EditRemoteDialog.cs index 482da43264..3d22e072e3 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/EditRemoteDialog.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/EditRemoteDialog.cs @@ -1,21 +1,21 @@ -// +// // EditRemoteDialog.cs -// +// // Author: // Lluis Sanchez Gual <lluis@novell.com> -// +// // Copyright (c) 2010 Novell, Inc (http://www.novell.com) -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -23,64 +23,59 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +using LibGit2Sharp; namespace MonoDevelop.VersionControl.Git { partial class EditRemoteDialog : Gtk.Dialog { - readonly RemoteSource remote; - readonly bool updating; - - public EditRemoteDialog (RemoteSource remote, bool isNew) + // TODO: Add user possibility to choose refspecs. + public EditRemoteDialog () : this (null) + { + } + + public EditRemoteDialog (Remote remote) { this.Build (); - this.remote = remote; - - updating = true; - entryName.Text = remote.Name; - entryUrl.Text = remote.FetchUrl ?? ""; - entryPushUrl.Text = string.IsNullOrEmpty (remote.PushUrl) ? remote.FetchUrl : remote.PushUrl; - if (!isNew) - checkImportTags.Visible = false; - updating = false; + if (remote != null) { + entryName.Text = remote.Name; + entryUrl.Text = remote.Url ?? ""; + entryPushUrl.Text = remote.PushUrl ?? ""; + } + checkImportTags.Visible = remote == null; UpdateButtons (); } - + + public string RemoteName { + get { return entryName.Text; } + } + + public string RemoteUrl { + get { return entryUrl.Text; } + } + + public string RemotePushUrl { + get { return entryPushUrl.Text; } + } + public bool ImportTags { get { return checkImportTags.Active; } } - + void UpdateButtons () { buttonOk.Sensitive = entryName.Text.Length > 0 && entryUrl.Text.Length > 0; } - + protected virtual void OnEntryNameChanged (object sender, System.EventArgs e) { - if (updating) - return; - remote.Name = entryName.Text; UpdateButtons (); } - + protected virtual void OnEntryUrlChanged (object sender, System.EventArgs e) { - if (updating) - return; - if (remote.FetchUrl == remote.PushUrl) - entryPushUrl.Text = entryUrl.Text; - remote.FetchUrl = entryUrl.Text; - UpdateButtons (); - } - - protected virtual void OnEntryPushUrlChanged (object sender, System.EventArgs e) - { - if (updating) - return; - remote.PushUrl = entryPushUrl.Text; UpdateButtons (); } } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/FilteredStatus.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/FilteredStatus.cs deleted file mode 100644 index 4f7efc334d..0000000000 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/FilteredStatus.cs +++ /dev/null @@ -1,85 +0,0 @@ -// -// SpecificStatus.cs -// -// Author: -// Alan McGovern <alan@xamarin.com> -// -// Copyright (c) 2012 Xamarin Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using System.Collections.Generic; -using System.Linq; - -using NGit; -using NGit.Treewalk; -using NGit.Treewalk.Filter; - -namespace MonoDevelop.VersionControl.Git -{ - class FilteredStatus : NGit.Api.StatusCommand - { - WorkingTreeIterator iter; - IndexDiff diff; - - IEnumerable<string> Files { - get; set; - } - - public FilteredStatus (NGit.Repository repository) - : base (repository) - { - } - - public FilteredStatus (NGit.Repository repository, IEnumerable<string> files) - : base (repository) - { - Files = files; - } - - public override NGit.Api.StatusCommand SetWorkingTreeIt (WorkingTreeIterator workingTreeIt) - { - iter = workingTreeIt; - return this; - } - - public override NGit.Api.Status Call () - { - if (iter == null) - iter = new FileTreeIterator (repo); - - diff = new IndexDiff (repo, Constants.HEAD, iter); - if (Files != null) { - var filters = Files.Where (f => f != ".").ToArray (); - if (filters.Length > 0) - diff.SetFilter (PathFilterGroup.CreateFromStrings (filters)); - } - - diff.Diff (); - return new NGit.Api.Status (diff); - } - - public virtual ICollection<string> GetIgnoredNotInIndex () - { - return diff.GetIgnoredNotInIndex (); - } - } -} - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitClient.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitClient.cs index aff517a19b..c9fa96748d 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitClient.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitClient.cs @@ -1,21 +1,21 @@ -// +// // GitClient.cs -// +// // Author: // Dale Ragan <dale.ragan@sinesignal.com> -// +// // Copyright (c) 2010 SineSignal, LLC -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -30,4 +30,3 @@ namespace MonoDevelop.VersionControl.Git { } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitCommitDialogExtension.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitCommitDialogExtension.cs index d5309881cd..041e94b036 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitCommitDialogExtension.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitCommitDialogExtension.cs @@ -1,23 +1,23 @@ -// +// // CommitDialogExtensionWidget.cs -// +// // Authors: // Lluis Sanchez Gual <lluis@novell.com> // Andrés G. Aragoneses <knocte@gmail.com> -// +// // Copyright (c) 2010 Novell, Inc (http://www.novell.com) // Copyright (c) 2013 Andrés G. Aragoneses -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -54,14 +54,14 @@ namespace MonoDevelop.VersionControl.Git } return false; } - + public override bool OnBeginCommit (ChangeSet changeSet) { // In this callback we check if the user information configured in Git // matches the user information configured in MonoDevelop. If the configurations // don't match, it shows a dialog asking the user what to do. - GitRepository repo = (GitRepository) changeSet.Repository; + var repo = (GitRepository) changeSet.Repository; Solution sol = null; // Locate the solution to which the changes belong @@ -85,7 +85,7 @@ namespace MonoDevelop.VersionControl.Git string user; string email; repo.GetUserInfo (out user, out email); - + string val = sol.UserProperties.GetValue<string> ("GitUserInfo"); if (val == "UsingMD") { // If the solution is configured to use the MD configuration, make sure the Git config is up to date. @@ -111,8 +111,8 @@ namespace MonoDevelop.VersionControl.Git // There is a conflict. Ask the user what to do string gitInfo = GetDesc (user, email); string mdInfo = GetDesc (sol.AuthorInformation.Name, sol.AuthorInformation.Email); - - UserInfoConflictDialog dlg = new UserInfoConflictDialog (mdInfo, gitInfo); + + var dlg = new UserInfoConflictDialog (mdInfo, gitInfo); try { if (MessageService.RunCustomDialog (dlg) == (int) Gtk.ResponseType.Ok) { if (dlg.UseMonoDevelopConfig) { @@ -131,7 +131,7 @@ namespace MonoDevelop.VersionControl.Git } return true; } - + static string GetDesc (string name, string email) { if (string.IsNullOrEmpty (name) && string.IsNullOrEmpty (email)) @@ -142,7 +142,7 @@ namespace MonoDevelop.VersionControl.Git email = GettextCatalog.GetString ("e-mail not configured"); return name + ", " + email; } - + public override void OnEndCommit (ChangeSet changeSet, bool success) { if (success && widget.PushAfterCommit) @@ -176,7 +176,7 @@ namespace MonoDevelop.VersionControl.Git var lines = text.Split ('\n'); if (lines.Length > 0 && lines [0].Length > maxLengthConventionForFirstLineOfCommitMessage) { textView.TooltipText = String.Format (GettextCatalog.GetString ( - "When using GIT, it is not recommended to surpass the character count of {0} in the first line of the commit message"), + "When using Git, it is not recommended to surpass the character count of {0} in the first line of the commit message"), maxLengthConventionForFirstLineOfCommitMessage); textView.HasTooltip = true; @@ -192,4 +192,3 @@ namespace MonoDevelop.VersionControl.Git } } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitCommitDialogExtensionWidget.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitCommitDialogExtensionWidget.cs index 989e4e4c49..700a73fbbc 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitCommitDialogExtensionWidget.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitCommitDialogExtensionWidget.cs @@ -1,21 +1,21 @@ -// +// // GitCommitDialogExtensionWidget.cs -// +// // Author: // Lluis Sanchez Gual <lluis@novell.com> -// +// // Copyright (c) 2011 Novell, Inc (http://www.novell.com) -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -34,37 +34,36 @@ namespace MonoDevelop.VersionControl.Git { this.Build (); } - + public bool PushAfterCommit { get { return checkPush.Active; } } - + public bool CommitterIsAuthor { get { return !checkAuthor.Active; } } - + public string AuthorName { get { return entryName.Text; } } - + public string AuthorMail { get { return entryEmail.Text; } } - protected void OnCheckAuthorToggled (object sender, System.EventArgs e) + protected void OnCheckAuthorToggled (object sender, EventArgs e) { authorBox.Visible = checkAuthor.Active; OnChanged (sender, e); } - - void OnChanged (object sender, System.EventArgs e) + + void OnChanged (object sender, EventArgs e) { if (Changed != null) Changed (this, EventArgs.Empty); } - + public event EventHandler Changed; } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitConfigurationDialog.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitConfigurationDialog.cs index 1d7faa7316..22a63e8490 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitConfigurationDialog.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitConfigurationDialog.cs @@ -1,21 +1,21 @@ -// +// // GitConfigurationDialog.cs -// +// // Author: // Lluis Sanchez Gual <lluis@novell.com> -// +// // Copyright (c) 2010 Novell, Inc (http://www.novell.com) -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -29,6 +29,7 @@ using Gtk; using MonoDevelop.Core; using MonoDevelop.Ide; using MonoDevelop.Components; +using LibGit2Sharp; namespace MonoDevelop.VersionControl.Git { @@ -38,82 +39,94 @@ namespace MonoDevelop.VersionControl.Git readonly ListStore storeBranches; readonly ListStore storeTags; readonly TreeStore storeRemotes; - + public GitConfigurationDialog (GitRepository repo) { this.Build (); this.repo = repo; this.HasSeparator = false; - + // Branches list - + storeBranches = new ListStore (typeof(Branch), typeof(string), typeof(string), typeof(string)); listBranches.Model = storeBranches; listBranches.HeadersVisible = true; - + listBranches.AppendColumn (GettextCatalog.GetString ("Branch"), new CellRendererText (), "markup", 1); listBranches.AppendColumn (GettextCatalog.GetString ("Tracking"), new CellRendererText (), "text", 2); listBranches.Selection.Changed += delegate { TreeIter it; - if (!listBranches.Selection.GetSelected (out it)) - return; + bool anythingSelected = + buttonRemoveBranch.Sensitive = buttonEditBranch.Sensitive = buttonSetDefaultBranch.Sensitive = listBranches.Selection.GetSelected (out it); + if (!anythingSelected) + return; string currentBranch = repo.GetCurrentBranch (); var b = (Branch) storeBranches.GetValue (it, 0); buttonRemoveBranch.Sensitive = b.Name != currentBranch; }; + buttonRemoveBranch.Sensitive = buttonEditBranch.Sensitive = buttonSetDefaultBranch.Sensitive = false; // Sources tree - - storeRemotes = new TreeStore (typeof(RemoteSource), typeof(string), typeof(string), typeof(string), typeof(string)); + + storeRemotes = new TreeStore (typeof(Remote), typeof(string), typeof(string), typeof(string), typeof(string)); treeRemotes.Model = storeRemotes; treeRemotes.HeadersVisible = true; - + treeRemotes.AppendColumn ("Remote Source / Branch", new CellRendererText (), "markup", 1); treeRemotes.AppendColumn ("Url", new CellRendererText (), "text", 2); + treeRemotes.Selection.Changed += delegate { + TreeIter it; + buttonTrackRemote.Sensitive = buttonFetch.Sensitive = buttonEditRemote.Sensitive = buttonRemoveRemote.Sensitive = treeRemotes.Selection.GetSelected (out it); + }; + buttonTrackRemote.Sensitive = buttonFetch.Sensitive = buttonEditRemote.Sensitive = buttonRemoveRemote.Sensitive = false; + // Tags list - + storeTags = new ListStore (typeof(string)); listTags.Model = storeTags; listTags.HeadersVisible = true; listTags.AppendColumn (GettextCatalog.GetString ("Tag"), new CellRendererText (), "text", 0); + listTags.Selection.Changed += delegate { + TreeIter it; + buttonRemoveTag.Sensitive = buttonPushTag.Sensitive = listTags.Selection.GetSelected (out it); + }; + buttonRemoveTag.Sensitive = buttonPushTag.Sensitive = false; + // Fill data - + FillBranches (); FillRemotes (); FillTags (); } - + void FillBranches () { - TreeViewState state = new TreeViewState (listBranches, 3); + var state = new TreeViewState (listBranches, 3); state.Save (); storeBranches.Clear (); string currentBranch = repo.GetCurrentBranch (); foreach (Branch branch in repo.GetBranches ()) { string text = branch.Name == currentBranch ? "<b>" + branch.Name + "</b>" : branch.Name; - storeBranches.AppendValues (branch, text, branch.Tracking, branch.Name); + storeBranches.AppendValues (branch, text, branch.IsTracking ? branch.TrackedBranch.Name : String.Empty, branch.Name); } state.Load (); } - + void FillRemotes () { - TreeViewState state = new TreeViewState (treeRemotes, 4); + var state = new TreeViewState (treeRemotes, 4); state.Save (); storeRemotes.Clear (); string currentRemote = repo.GetCurrentRemote (); - foreach (RemoteSource remote in repo.GetRemotes ()) { + foreach (Remote remote in repo.GetRemotes ()) { + // Take into account fetch/push ref specs. string text = remote.Name == currentRemote ? "<b>" + remote.Name + "</b>" : remote.Name; - string url; - if (remote.FetchUrl == remote.PushUrl) - url = remote.FetchUrl; - else - url = remote.FetchUrl + " (fetch)\n" + remote.PushUrl + " (push)"; + string url = remote.Url; TreeIter it = storeRemotes.AppendValues (remote, text, url, null, remote.Name); foreach (string branch in repo.GetRemoteBranches (remote.Name)) storeRemotes.AppendValues (it, null, branch, null, branch, remote.Name + "/" + branch); @@ -128,10 +141,10 @@ namespace MonoDevelop.VersionControl.Git storeTags.AppendValues (tag); } } - + protected virtual void OnButtonAddBranchClicked (object sender, EventArgs e) { - var dlg = new EditBranchDialog (repo, null, true); + var dlg = new EditBranchDialog (repo); try { if (MessageService.RunCustomDialog (dlg) == (int) ResponseType.Ok) { repo.CreateBranch (dlg.BranchName, dlg.TrackSource); @@ -141,14 +154,14 @@ namespace MonoDevelop.VersionControl.Git dlg.Destroy (); } } - + protected virtual void OnButtonEditBranchClicked (object sender, EventArgs e) { TreeIter it; if (!listBranches.Selection.GetSelected (out it)) return; - Branch b = (Branch) storeBranches.GetValue (it, 0); - var dlg = new EditBranchDialog (repo, b, false); + var b = (Branch) storeBranches.GetValue (it, 0); + var dlg = new EditBranchDialog (repo, b.Name, b.IsTracking ? b.TrackedBranch.Name : String.Empty); try { if (MessageService.RunCustomDialog (dlg) == (int) ResponseType.Ok) { if (dlg.BranchName != b.Name) { @@ -165,13 +178,13 @@ namespace MonoDevelop.VersionControl.Git dlg.Destroy (); } } - + protected virtual void OnButtonRemoveBranchClicked (object sender, EventArgs e) { TreeIter it; if (!listBranches.Selection.GetSelected (out it)) return; - Branch b = (Branch) storeBranches.GetValue (it, 0); + var b = (Branch) storeBranches.GetValue (it, 0); string txt = null; if (!repo.IsBranchMerged (b.Name)) txt = GettextCatalog.GetString ("WARNING: The branch has not yet been merged to HEAD"); @@ -184,63 +197,63 @@ namespace MonoDevelop.VersionControl.Git } } } - + protected virtual void OnButtonSetDefaultBranchClicked (object sender, EventArgs e) { TreeIter it; if (!listBranches.Selection.GetSelected (out it)) return; - Branch b = (Branch) storeBranches.GetValue (it, 0); + var b = (Branch) storeBranches.GetValue (it, 0); GitService.SwitchToBranch (repo, b.Name); FillBranches (); } - + protected virtual void OnButtonAddRemoteClicked (object sender, EventArgs e) { - var remote = new RemoteSource (); - var dlg = new EditRemoteDialog (remote, true); + var dlg = new EditRemoteDialog (); try { if (MessageService.RunCustomDialog (dlg) == (int) ResponseType.Ok) { - repo.AddRemote (remote, dlg.ImportTags); + repo.AddRemote (dlg.RemoteName, dlg.RemoteUrl, dlg.ImportTags); FillRemotes (); } } finally { dlg.Destroy (); } } - + protected virtual void OnButtonEditRemoteClicked (object sender, EventArgs e) { TreeIter it; if (!treeRemotes.Selection.GetSelected (out it)) return; - - RemoteSource remote = (RemoteSource) storeRemotes.GetValue (it, 0); + + var remote = (Remote) storeRemotes.GetValue (it, 0); if (remote == null) return; - string oldName = remote.Name; - - var dlg = new EditRemoteDialog (remote, false); + var dlg = new EditRemoteDialog (remote); try { if (MessageService.RunCustomDialog (dlg) == (int) ResponseType.Ok) { - if (remote.Name != oldName) - repo.RenameRemote (oldName, remote.Name); - repo.UpdateRemote (remote); + if (remote.Name != dlg.RemoteName) + repo.RenameRemote (remote.Name, dlg.RemoteName); + if (remote.Url != dlg.RemoteUrl) + repo.ChangeRemoteUrl (remote.Name, dlg.RemoteUrl); + if (remote.Url != dlg.RemotePushUrl) + repo.ChangeRemotePushUrl (remote.Name, dlg.RemotePushUrl); FillRemotes (); } } finally { dlg.Destroy (); } } - + protected virtual void OnButtonRemoveRemoteClicked (object sender, EventArgs e) { TreeIter it; if (!treeRemotes.Selection.GetSelected (out it)) return; - RemoteSource remote = (RemoteSource) storeRemotes.GetValue (it, 0); + var remote = (Remote) storeRemotes.GetValue (it, 0); if (remote == null) return; @@ -249,7 +262,7 @@ namespace MonoDevelop.VersionControl.Git FillRemotes (); } } - + void UpdateRemoteButtons () { TreeIter it; @@ -257,11 +270,11 @@ namespace MonoDevelop.VersionControl.Git buttonAddRemote.Sensitive = buttonEditRemote.Sensitive = buttonRemoveRemote.Sensitive = buttonTrackRemote.Sensitive = false; return; } - RemoteSource remote = (RemoteSource) storeRemotes.GetValue (it, 0); + var remote = (Remote) storeRemotes.GetValue (it, 0); buttonTrackRemote.Sensitive = remote == null; buttonAddRemote.Sensitive = buttonEditRemote.Sensitive = buttonRemoveRemote.Sensitive = remote != null; } - + protected virtual void OnButtonTrackRemoteClicked (object sender, EventArgs e) { TreeIter it; @@ -270,18 +283,14 @@ namespace MonoDevelop.VersionControl.Git string branchName = (string) storeRemotes.GetValue (it, 3); if (branchName == null) return; - + storeRemotes.IterParent (out it, it); - RemoteSource remote = (RemoteSource) storeRemotes.GetValue (it, 0); - - Branch b = new Branch (); - b.Name = branchName; - b.Tracking = remote.Name + "/" + branchName; - - var dlg = new EditBranchDialog (repo, b, true); + var remote = (Remote) storeRemotes.GetValue (it, 0); + + var dlg = new EditBranchDialog (repo, branchName, remote.Name + "/" + branchName); try { if (MessageService.RunCustomDialog (dlg) == (int) ResponseType.Ok) { - repo.CreateBranch (dlg.BranchName, dlg.TrackSource); + repo.SetBranchTrackSource (dlg.BranchName, dlg.TrackSource); FillBranches (); } } finally { @@ -292,7 +301,8 @@ namespace MonoDevelop.VersionControl.Git protected void OnButtonNewTagClicked (object sender, EventArgs e) { using (var dlg = new GitSelectRevisionDialog (repo)) { - if (dlg.Run () != Xwt.Command.Ok) + Xwt.WindowFrame parent = Xwt.Toolkit.CurrentEngine.WrapWindow (this); + if (dlg.Run (parent) != Xwt.Command.Ok) return; repo.AddTag (dlg.TagName, dlg.SelectedRevision, dlg.TagMessage); @@ -313,8 +323,26 @@ namespace MonoDevelop.VersionControl.Git protected virtual void OnButtonPushTagClicked (object sender, EventArgs e) { - repo.PushAllTags (); + TreeIter it; + if (!listTags.Selection.GetSelected (out it)) + return; + + string tagName = (string) storeTags.GetValue (it, 0); + repo.PushTag (tagName); + } + + protected void OnButtonFetchClicked (object sender, EventArgs e) + { + TreeIter it; + if (!treeRemotes.Selection.GetSelected (out it)) + return; + + string remoteName = (string) storeRemotes.GetValue (it, 4); + if (remoteName == null) + return; + + repo.Fetch (VersionControlService.GetProgressMonitor ("Fetching remote..."), remoteName); + FillRemotes (); } } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitCredentials.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitCredentials.cs index 4c6d20f79c..c253d12acb 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitCredentials.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitCredentials.cs @@ -1,21 +1,21 @@ -// +// // GitCredentials.cs -// +// // Author: // Lluis Sanchez Gual <lluis@novell.com> -// +// // Copyright (c) 2010 Novell, Inc (http://www.novell.com) -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -24,113 +24,199 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. using System; -using System.Linq; using MonoDevelop.Core; using MonoDevelop.Ide; -using NGit.Transport; +using LibGit2Sharp; +using System.IO; +using System.Collections.Generic; +using MonoDevelop.Components; namespace MonoDevelop.VersionControl.Git { - sealed class GitCredentials: CredentialsProvider + static class GitCredentials { - bool HasReset { - get; set; - } - - public override bool IsInteractive () - { - return true; - } - - public override bool Supports (params CredentialItem[] items) + // Gather keys on initialize. + static readonly List<string> Keys = new List<string> (); + static readonly Dictionary<string, int> KeyForUrl = new Dictionary<string, int> (); + static readonly Dictionary<string, bool> AgentForUrl = new Dictionary<string, bool> (); + + static string urlUsed; + static bool agentUsed; + static int keyUsed = -1; + static bool nativePasswordUsed; + + static GitCredentials () { - return true; + string keyStorage = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.Personal), ".ssh"); + if (!Directory.Exists (keyStorage)) + return; + + foreach (var privateKey in Directory.EnumerateFiles (keyStorage)) { + string publicKey = privateKey + ".pub"; + if (File.Exists (publicKey) && !KeyHasPassphrase (privateKey)) + Keys.Add (privateKey); + } } - public override bool Get (URIish uri, params CredentialItem[] items) + public static Credentials TryGet (string url, string userFromUrl, SupportedCredentialTypes types) { - bool result = false; - CredentialItem.Password passwordItem = null; - CredentialItem.StringType passphraseItem = null; - + bool result = true; + Uri uri = null; + + urlUsed = url; + // We always need to run the TryGet* methods as we need the passphraseItem/passwordItem populated even // if the password store contains an invalid password/no password - if (TryGetUsernamePassword (uri, items, out passwordItem) || TryGetPassphrase (uri, items, out passphraseItem)) { - // If the password store has a password and we already tried using it, it could be incorrect. - // If this happens, do not return true and ask the user for a new password. - if (!HasReset) { - return true; + if ((types & SupportedCredentialTypes.UsernamePassword) != 0) { + uri = new Uri (url); + string username; + string password; + if (!nativePasswordUsed && TryGetUsernamePassword (uri, out username, out password)) { + nativePasswordUsed = true; + return new UsernamePasswordCredentials { + Username = username, + Password = password + }; } } - DispatchService.GuiSyncDispatch (delegate { - CredentialsDialog dlg = new CredentialsDialog (uri, items); - try { - result = MessageService.ShowCustomDialog (dlg) == (int)Gtk.ResponseType.Ok; - } finally { - dlg.Destroy (); + Credentials cred; + if ((types & SupportedCredentialTypes.UsernamePassword) != 0) + cred = new UsernamePasswordCredentials (); + else { + // Try ssh-agent on Linux. + if (!Platform.IsWindows && !agentUsed) { + bool agentUsable; + if (!AgentForUrl.TryGetValue (url, out agentUsable)) + AgentForUrl [url] = agentUsable = true; + + if (agentUsable) { + agentUsed = true; + return new SshAgentCredentials { + Username = userFromUrl, + }; + } } + + int key; + if (!KeyForUrl.TryGetValue (url, out key)) { + if (keyUsed + 1 < Keys.Count) + keyUsed++; + else { + SelectFileDialog dlg = null; + bool success = false; + + DispatchService.GuiSyncDispatch (() => { + dlg = new SelectFileDialog (GettextCatalog.GetString ("Select a private SSH key to use.")); + dlg.ShowHidden = true; + dlg.CurrentFolder = Environment.GetFolderPath (Environment.SpecialFolder.Personal); + success = dlg.Run (); + }); + if (!success || !File.Exists (dlg.SelectedFile + ".pub")) + throw new VersionControlException (GettextCatalog.GetString ("Invalid credentials were supplied. Aborting operation.")); + + cred = new SshUserKeyCredentials { + Username = userFromUrl, + Passphrase = "", + PrivateKey = dlg.SelectedFile, + PublicKey = dlg.SelectedFile + ".pub", + }; + + if (KeyHasPassphrase (dlg.SelectedFile)) { + DispatchService.GuiSyncDispatch (delegate { + result = MessageService.ShowCustomDialog (new CredentialsDialog (url, types, cred)) == (int)Gtk.ResponseType.Ok; + }); + } + + if (result) + return cred; + throw new VersionControlException (GettextCatalog.GetString ("Invalid credentials were supplied. Aborting operation.")); + } + } else + keyUsed = key; + + cred = new SshUserKeyCredentials { + Username = userFromUrl, + Passphrase = "", + PrivateKey = Keys [keyUsed], + PublicKey = Keys [keyUsed] + ".pub", + }; + return cred; + } + + DispatchService.GuiSyncDispatch (delegate { + result = MessageService.ShowCustomDialog (new CredentialsDialog (url, types, cred)) == (int)Gtk.ResponseType.Ok; }); - - HasReset = false; + if (result) { - var user = items.OfType<CredentialItem.Username> ().FirstOrDefault (); - if (passwordItem != null) { - PasswordService.AddWebUserNameAndPassword (new Uri (uri.ToString ()), user.GetValue (), new string (passwordItem.GetValue ())); - } else if (passphraseItem != null) { - PasswordService.AddWebPassword (new Uri (uri.ToString ()), passphraseItem.GetValue ()); + if ((types & SupportedCredentialTypes.UsernamePassword) != 0) { + var upcred = (UsernamePasswordCredentials)cred; + if (!string.IsNullOrEmpty (upcred.Password)) { + PasswordService.AddWebUserNameAndPassword (uri, upcred.Username, upcred.Password); + } } } - return result; + + return cred; } - - public override void Reset (URIish uri) + + static bool KeyHasPassphrase (string key) { - HasReset = true; + return File.ReadAllText (key).Contains ("Proc-Type: 4,ENCRYPTED"); } - - static bool TryGetPassphrase (URIish uri, CredentialItem[] items, out CredentialItem.StringType passphraseItem) + + static bool TryGetPassphrase (Uri uri, out string passphrase) { - var actualUrl = new Uri (uri.ToString ()); - var passphrase = (CredentialItem.StringType) items.FirstOrDefault (i => i is CredentialItem.StringType); - - if (items.Length == 1 && passphrase != null) { - passphraseItem = passphrase; - - var passphraseValue = PasswordService.GetWebPassword (actualUrl); - if (passphraseValue != null) { - passphrase.SetValue (passphraseValue); - return true; - } - } else { - passphraseItem = null; + var passphraseValue = PasswordService.GetWebPassword (uri); + if (passphraseValue != null) { + passphrase = passphraseValue; + return true; } - + + passphrase = null; return false; } - - static bool TryGetUsernamePassword (URIish uri, CredentialItem[] items, out CredentialItem.Password passwordItem) + + static bool TryGetUsernamePassword (Uri uri, out string username, out string password) { - var actualUrl = new Uri (uri.ToString ()); - var username = (CredentialItem.Username) items.FirstOrDefault (i => i is CredentialItem.Username); - var password = (CredentialItem.Password) items.FirstOrDefault (i => i is CredentialItem.Password); - - if (items.Length == 2 && username != null && password != null) { - passwordItem = password; - - var cred = PasswordService.GetWebUserNameAndPassword (actualUrl); - if (cred != null) { - username.SetValue (cred.Item1); - password.SetValueNoCopy (cred.Item2.ToArray ()); - return true; - } - } else { - passwordItem = null; + var cred = PasswordService.GetWebUserNameAndPassword (uri); + if (cred != null) { + username = cred.Item1; + password = cred.Item2; + return true; } + username = null; + password = null; return false; } + + internal static void StoreCredentials () + { + nativePasswordUsed = false; + + if (!string.IsNullOrEmpty (urlUsed)) + if (keyUsed != -1) + KeyForUrl [urlUsed] = keyUsed; + + Cleanup (); + } + + internal static void InvalidateCredentials () + { + if (!string.IsNullOrEmpty (urlUsed)) + if (AgentForUrl.ContainsKey (urlUsed)) + AgentForUrl [urlUsed] &= !agentUsed; + + Cleanup (); + } + + static void Cleanup () + { + urlUsed = null; + agentUsed = false; + keyUsed = -1; + } } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitNodeBuilderExtension.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitNodeBuilderExtension.cs index 03561045fe..3156a8e2a0 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitNodeBuilderExtension.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitNodeBuilderExtension.cs @@ -1,21 +1,21 @@ -// +// // GitNodeBuilderExtension.cs -// +// // Author: // Lluis Sanchez Gual <lluis@novell.com> -// +// // Copyright (c) 2010 Novell, Inc (http://www.novell.com) -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -36,56 +36,56 @@ namespace MonoDevelop.VersionControl.Git sealed class GitNodeBuilderExtension: NodeBuilderExtension { readonly Dictionary<FilePath,WorkspaceObject> repos = new Dictionary<FilePath, WorkspaceObject> (); - + protected override void Initialize () { base.Initialize (); IdeApp.FocusIn += HandleApplicationFocusIn; GitRepository.BranchSelectionChanged += HandleBranchSelectionChanged; } - + public override void Dispose () { IdeApp.FocusIn -= HandleApplicationFocusIn; GitRepository.BranchSelectionChanged -= HandleBranchSelectionChanged; base.Dispose (); } - + public override bool CanBuildNode (Type dataType) { return typeof(WorkspaceObject).IsAssignableFrom (dataType); } - + public override void BuildNode (ITreeBuilder treeBuilder, object dataObject, NodeInfo nodeInfo) { - WorkspaceObject ob = (WorkspaceObject) dataObject; - GitRepository rep = VersionControlService.GetRepository (ob) as GitRepository; + var ob = (WorkspaceObject) dataObject; + var rep = VersionControlService.GetRepository (ob) as GitRepository; if (rep != null) { WorkspaceObject rob; - if (repos.TryGetValue (rep.RootPath.CanonicalPath, out rob)) { + if (repos.TryGetValue (rep.RootPath, out rob)) { if (ob == rob) nodeInfo.Label += " (" + rep.GetCurrentBranch () + ")"; } } } - + public override void OnNodeAdded (object dataObject) { - WorkspaceObject ob = (WorkspaceObject) dataObject; - GitRepository rep = VersionControlService.GetRepository (ob) as GitRepository; - if (rep != null && !repos.ContainsKey (rep.RootPath.CanonicalPath)) { + var ob = (WorkspaceObject) dataObject; + var rep = VersionControlService.GetRepository (ob) as GitRepository; + if (rep != null && !repos.ContainsKey (rep.RootPath)) { repos [rep.RootPath] = ob; } } - + public override void OnNodeRemoved (object dataObject) { - WorkspaceObject ob = (WorkspaceObject) dataObject; - GitRepository rep = VersionControlService.GetRepository (ob) as GitRepository; + var ob = (WorkspaceObject) dataObject; + var rep = VersionControlService.GetRepository (ob) as GitRepository; WorkspaceObject rob; - if (rep != null && repos.TryGetValue (rep.RootPath.CanonicalPath, out rob)) { + if (rep != null && repos.TryGetValue (rep.RootPath, out rob)) { if (ob == rob) - repos.Remove (rep.RootPath.CanonicalPath); + repos.Remove (rep.RootPath); } } @@ -104,4 +104,3 @@ namespace MonoDevelop.VersionControl.Git } } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitOptionsPanel.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitOptionsPanel.cs index 9bc3db16cc..5a09a60d17 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitOptionsPanel.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitOptionsPanel.cs @@ -1,21 +1,21 @@ -// +// // GitOptionsPanel.cs -// +// // Author: // Lluis Sanchez Gual <lluis@novell.com> -// +// // Copyright (c) 2011 Novell, Inc (http://www.novell.com) -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -42,4 +42,3 @@ namespace MonoDevelop.VersionControl.Git } } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitOptionsPanelWidget.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitOptionsPanelWidget.cs index eddbdb6a27..fb2c8d024a 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitOptionsPanelWidget.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitOptionsPanelWidget.cs @@ -1,21 +1,21 @@ -// +// // GitOptionsPanelWidget.cs -// +// // Author: // Lluis Sanchez Gual <lluis@novell.com> -// +// // Copyright (c) 2011 Novell, Inc (http://www.novell.com) -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -36,7 +36,7 @@ namespace MonoDevelop.VersionControl.Git checkStashUpdate.Active = GitService.StashUnstashWhenUpdating; checkStashBranch.Active = GitService.StashUnstashWhenSwitchingBranches; } - + public void ApplyChanges () { GitService.UseRebaseOptionWhenPulling = checkRebase.Active; @@ -45,4 +45,3 @@ namespace MonoDevelop.VersionControl.Git } } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitRepository.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitRepository.cs index 119cc2708f..02f443d27d 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitRepository.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitRepository.cs @@ -1,21 +1,21 @@ -// +// // GitRepository.cs -// +// // Author: // Lluis Sanchez Gual <lluis@novell.com> -// +// // Copyright (c) 2010 Novell, Inc (http://www.novell.com) -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -33,18 +33,8 @@ using MonoDevelop.Core; using System.Collections.Generic; using System.Text; using MonoDevelop.Ide; -using NGit; -using NGit.Storage.File; -using NGit.Revwalk; -using NGit.Api; -using NGit.Treewalk; -using NGit.Treewalk.Filter; -using NGit.Dircache; -using NGit.Transport; -using NGit.Diff; -using NGit.Merge; -using NGit.Submodule; using ProgressMonitor = MonoDevelop.Core.ProgressMonitor; +using LibGit2Sharp; namespace MonoDevelop.VersionControl.Git { @@ -59,9 +49,7 @@ namespace MonoDevelop.VersionControl.Git public sealed class GitRepository : UrlBasedRepository { - static readonly byte[] EmptyContent = new byte[0]; - - internal LocalGitRepository RootRepository { + public LibGit2Sharp.Repository RootRepository { get; set; } @@ -75,39 +63,48 @@ namespace MonoDevelop.VersionControl.Git public GitRepository (VersionControlSystem vcs, FilePath path, string url) : base (vcs) { RootPath = path; - RootRepository = new LocalGitRepository (path.Combine (Constants.DOT_GIT)); + string discovered = LibGit2Sharp.Repository.Discover (path); + if (!string.IsNullOrEmpty (discovered)) + RootRepository = new LibGit2Sharp.Repository (discovered); Url = url; } - + public override void Dispose () { - ((GitVersionControl)VersionControlSystem).UnregisterRepo (this); + if (VersionControlSystem != null) + ((GitVersionControl)VersionControlSystem).UnregisterRepo (this); + + if (RootRepository != null) + RootRepository.Dispose (); + foreach (var rep in cachedSubmodules) + rep.Item2.Dispose (); base.Dispose (); } - + public override string[] SupportedProtocols { get { - return new string[] {"git", "ssh", "http", "https", "ftp", "ftps", "rsync", "file"}; - } - } - - public override string[] SupportedNonUrlProtocols { - get { - return new string[] {"ssh/scp"}; + return new [] {"git", "ssh", "http", "https", /*"ftp", "ftps", "rsync",*/ "file"}; } } - + public override bool IsUrlValid (string url) { - try { - URIish u = new URIish (url); - if (!string.IsNullOrEmpty (u.GetHost ())) + if (url.Contains (':')) { + var tokens = url.Split (new[] { ':' }, 2); + if (Uri.IsWellFormedUriString (tokens [0], UriKind.RelativeOrAbsolute) || + Uri.IsWellFormedUriString (tokens [1], UriKind.RelativeOrAbsolute)) return true; - } catch { } + return base.IsUrlValid (url); } - + + /*public override string[] SupportedNonUrlProtocols { + get { + return new string[] {"ssh/scp"}; + } + } + public override string Protocol { get { string p = base.Protocol; @@ -115,16 +112,16 @@ namespace MonoDevelop.VersionControl.Git return p; return IsUrlValid (Url) ? "ssh/scp" : null; } - } + }*/ public override void CopyConfigurationFrom (Repository other) { base.CopyConfigurationFrom (other); - GitRepository r = (GitRepository)other; + var r = (GitRepository)other; RootPath = r.RootPath; if (!RootPath.IsNullOrEmpty) - RootRepository = new LocalGitRepository (RootPath); + RootRepository = new LibGit2Sharp.Repository (RootPath); } public override string LocationDescription { @@ -137,118 +134,227 @@ namespace MonoDevelop.VersionControl.Git public override string GetBaseText (FilePath localFile) { - RevCommit c = GetHeadCommit (GetRepository (localFile)); - if (c == null) - return string.Empty; - return GetCommitTextContent (c, localFile); + Commit c = GetHeadCommit (GetRepository (localFile)); + return c == null ? string.Empty : GetCommitTextContent (c, localFile); } - - static RevCommit GetHeadCommit (NGit.Repository repository) + + static Commit GetHeadCommit (LibGit2Sharp.Repository repository) { - RevWalk rw = new RevWalk (repository); - ObjectId headId = repository.Resolve (Constants.HEAD); - if (headId == null) - return null; - return rw.ParseCommit (headId); + return repository.Head.Tip; } public StashCollection GetStashes () { - return GetStashes (RootRepository); + return RootRepository.Stashes; } - public static StashCollection GetStashes (NGit.Repository repository) + const CheckoutNotifyFlags refreshFlags = CheckoutNotifyFlags.Updated | CheckoutNotifyFlags.Conflict | CheckoutNotifyFlags.Untracked | CheckoutNotifyFlags.Dirty; + bool RefreshFile (string path, CheckoutNotifyFlags flags) { - return new StashCollection (repository); + FilePath fp = RootRepository.FromGitPath (path); + if (IdeApp.IsInitialized) { + MonoDevelop.Ide.Gui.Document doc = IdeApp.Workbench.GetDocument (fp); + if (doc != null) + doc.Reload (); + } + FileService.NotifyFileChanged (fp); + VersionControlService.NotifyFileStatusChanged (new FileUpdateEventArgs (this, fp, false)); + return true; } - IEnumerable<string> GetSubmodulePaths () + static bool OnTransferProgress (TransferProgress tp, ProgressMonitor monitor, ref int progress) { - if (!File.Exists (RootPath.Combine (Constants.DOT_GIT_MODULES))) - return new List<string> (); + if (progress == 0 && tp.ReceivedObjects == 0) + monitor.BeginTask ("Receiving and indexing objects", 2 * tp.TotalObjects); + + int currentProgress = tp.ReceivedObjects + tp.IndexedObjects; + int steps = currentProgress - progress; + monitor.Step (steps); + progress = currentProgress; + + if (tp.IndexedObjects >= tp.TotalObjects) + monitor.EndTask (); + + return !monitor.CancellationToken.IsCancellationRequested; + } + + static void OnCheckoutProgress (int completedSteps, int totalSteps, ProgressMonitor monitor, ref int progress) + { + if (progress == 0 && completedSteps == 0) + monitor.BeginTask ("Checking out files", totalSteps); + + int steps = completedSteps - progress; + monitor.Step (steps); + progress = completedSteps; + + if (completedSteps >= totalSteps) + monitor.EndTask (); + } + + void NotifyFilesChangedForStash (Stash stash) + { + // HACK: Notify file changes. + foreach (var entry in RootRepository.Diff.Compare<TreeChanges> (stash.WorkTree.Tree, stash.Base.Tree)) { + if (entry.Status == ChangeKind.Deleted || entry.Status == ChangeKind.Renamed) { + FileService.NotifyFileRemoved (RootRepository.FromGitPath (entry.OldPath)); + } else { + FileService.NotifyFileChanged (RootRepository.FromGitPath (entry.Path)); + } + } + } + + public StashApplyStatus ApplyStash (ProgressMonitor monitor, int stashIndex) + { + if (monitor != null) + monitor.BeginTask ("Applying stash", 1); + + int progress = 0; + var res = RootRepository.Stashes.Apply (stashIndex, StashApplyModifiers.Default, new CheckoutOptions { + OnCheckoutProgress = (path, completedSteps, totalSteps) => OnCheckoutProgress (completedSteps, totalSteps, monitor, ref progress), + OnCheckoutNotify = RefreshFile, + CheckoutNotifyFlags = refreshFlags, + }); + + NotifyFilesChangedForStash (RootRepository.Stashes [stashIndex]); + if (monitor != null) + monitor.EndTask (); + + return res; + } + + public StashApplyStatus PopStash (ProgressMonitor monitor, int stashIndex) + { + if (monitor != null) + monitor.BeginTask ("Applying stash", 1); + + var stash = RootRepository.Stashes [stashIndex]; + int progress = 0; + var res = RootRepository.Stashes.Pop (stashIndex, StashApplyModifiers.Default, new CheckoutOptions { + OnCheckoutProgress = (path, completedSteps, totalSteps) => OnCheckoutProgress (completedSteps, totalSteps, monitor, ref progress), + OnCheckoutNotify = RefreshFile, + CheckoutNotifyFlags = refreshFlags, + }); + NotifyFilesChangedForStash (stash); + if (monitor != null) + monitor.EndTask (); - var lines = File.ReadAllLines (RootPath.Combine (Constants.DOT_GIT_MODULES)); - // Parses .gitmodules to get all submodules paths. - var res = lines.Where (l => l.Contains ("path = ")).Select (l => l.Substring (l.LastIndexOf (" ", StringComparison.Ordinal) + 1)); return res; } + public bool TryCreateStash (ProgressMonitor monitor, string message, out Stash stash) + { + Signature sig = GetSignature (); + stash = null; + if (sig == null) + return false; + + if (monitor != null) + monitor.BeginTask ("Stashing changes", 1); + + stash = RootRepository.Stashes.Add (sig, message, StashModifiers.Default | StashModifiers.IncludeUntracked); + + if (monitor != null) + monitor.EndTask (); + return true; + } + + internal Signature GetSignature() + { + // TODO: Investigate Configuration.BuildSignature. + string name; + string email; + + GetUserInfo (out name, out email); + if (name == null || email == null) + return null; + + return new Signature (name, email, DateTimeOffset.Now); + } + DateTime cachedSubmoduleTime = DateTime.MinValue; - NGit.Repository[] cachedSubmodules = new NGit.Repository[0]; - NGit.Repository[] CachedSubmodules { + Tuple<FilePath, LibGit2Sharp.Repository>[] cachedSubmodules = new Tuple<FilePath, LibGit2Sharp.Repository>[0]; + Tuple<FilePath, LibGit2Sharp.Repository>[] CachedSubmodules { get { - var submoduleWriteTime = File.GetLastWriteTimeUtc(RootPath.Combine(Constants.DOT_GIT_MODULES)); + var submoduleWriteTime = File.GetLastWriteTimeUtc(RootPath.Combine(".gitmodules")); if (cachedSubmoduleTime != submoduleWriteTime) { cachedSubmoduleTime = submoduleWriteTime; - var submoduleStatus = new NGit.Api.Git (RootRepository).SubmoduleStatus (); - foreach (var submodule in GetSubmodulePaths ()) - submoduleStatus.AddPath (submodule); - - cachedSubmodules = submoduleStatus.Call () - .Select(s => SubmoduleWalk.GetSubmoduleRepository (RootRepository, s.Key)) - .Where(s => s != null) // TODO: Make this so we can tell user to clone them. - .ToArray (); + cachedSubmodules = RootRepository.Submodules.Select (s => { + var fp = new FilePath (Path.Combine (RootRepository.Info.WorkingDirectory, s.Path.Replace ('/', Path.DirectorySeparatorChar))).CanonicalPath; + return new Tuple<FilePath, LibGit2Sharp.Repository> (fp, new LibGit2Sharp.Repository (fp)); + }).ToArray (); } return cachedSubmodules; } } - NGit.Repository GetRepository (FilePath localPath) + LibGit2Sharp.Repository GetRepository (FilePath localPath) { return GroupByRepository (new [] { localPath }).First ().Key; } - IEnumerable<IGrouping<NGit.Repository, FilePath>> GroupByRepository (IEnumerable<FilePath> files) + IEnumerable<IGrouping<LibGit2Sharp.Repository, FilePath>> GroupByRepository (IEnumerable<FilePath> files) { var cache = CachedSubmodules; - return files.GroupBy (f => cache.FirstOrDefault (s => { - var fullPath = s.WorkTree.ToString (); - return f.IsChildPathOf (fullPath) || f.FullPath == fullPath; - }) ?? RootRepository); + return files.GroupBy (f => { + var res = cache.FirstOrDefault (s => f.IsChildPathOf (s.Item1) || f.FullPath == s.Item1); + return res != null ? res.Item2 : RootRepository; + }); } protected override Revision[] OnGetHistory (FilePath localFile, Revision since) { - List<Revision> revs = new List<Revision> (); + var revs = new List<Revision> (); var repository = GetRepository (localFile); + var sinceRev = (GitRevision)since; var hc = GetHeadCommit (repository); if (hc == null) return new GitRevision [0]; - RevWalk walk = new RevWalk (repository); - string path = repository.ToGitPath (localFile); - if (path != ".") - walk.SetTreeFilter (FollowFilter.Create (path)); - walk.MarkStart (hc); - - foreach (RevCommit commit in walk) { - PersonIdent author = commit.GetAuthorIdent (); - GitRevision rev = new GitRevision (this, repository, commit.Id.Name, author.GetWhen().ToLocalTime (), author.GetName (), commit.GetFullMessage ()); - rev.Email = author.GetEmailAddress (); - rev.ShortMessage = commit.GetShortMessage (); - rev.Commit = commit; - rev.FileForChanges = localFile; + IEnumerable<Commit> commits = repository.Commits; + if (localFile.CanonicalPath != RootPath.CanonicalPath) { + var localPath = repository.ToGitPath (localFile); + commits = commits.Where (c => c.Parents.Count () == 1 && c.Tree [localPath] != null && + (c.Parents.FirstOrDefault ().Tree [localPath] == null || + c.Tree [localPath].Target.Id != c.Parents.FirstOrDefault ().Tree [localPath].Target.Id)); + } + + foreach (var commit in commits) { + var author = commit.Author; + var rev = new GitRevision (this, repository, commit, author.When.LocalDateTime, author.Name, commit.Message) { + Email = author.Email, + ShortMessage = commit.MessageShort, + FileForChanges = localFile, + }; revs.Add (rev); } + return revs.ToArray (); } - + protected override RevisionPath[] OnGetRevisionChanges (Revision revision) { - GitRevision rev = (GitRevision) revision; + var rev = (GitRevision) revision; if (rev.Commit == null) return new RevisionPath [0]; - List<RevisionPath> paths = new List<RevisionPath> (); - foreach (var entry in GitUtil.GetCommitChanges (rev.GitRepository, rev.Commit)) { - if (entry.GetChangeType () == DiffEntry.ChangeType.ADD) - paths.Add (new RevisionPath (rev.GitRepository.FromGitPath (entry.GetNewPath ()), RevisionAction.Add, null)); - if (entry.GetChangeType () == DiffEntry.ChangeType.DELETE) - paths.Add (new RevisionPath (rev.GitRepository.FromGitPath (entry.GetOldPath ()), RevisionAction.Delete, null)); - if (entry.GetChangeType () == DiffEntry.ChangeType.MODIFY) - paths.Add (new RevisionPath (rev.GitRepository.FromGitPath (entry.GetNewPath ()), RevisionAction.Modify, null)); - } + var paths = new List<RevisionPath> (); + var parent = rev.Commit.Parents.FirstOrDefault (); + var changes = rev.GitRepository.Diff.Compare <TreeChanges>(parent != null ? parent.Tree : null, rev.Commit.Tree); + + foreach (var entry in changes.Added) + paths.Add (new RevisionPath (rev.GitRepository.FromGitPath (entry.Path), RevisionAction.Add, null)); + foreach (var entry in changes.Copied) + paths.Add (new RevisionPath (rev.GitRepository.FromGitPath (entry.Path), RevisionAction.Add, null)); + foreach (var entry in changes.Deleted) + paths.Add (new RevisionPath (rev.GitRepository.FromGitPath (entry.OldPath), RevisionAction.Delete, null)); + foreach (var entry in changes.Renamed) + paths.Add (new RevisionPath (rev.GitRepository.FromGitPath (entry.Path), RevisionAction.Replace, null)); + foreach (var entry in changes.Modified) + paths.Add (new RevisionPath (rev.GitRepository.FromGitPath (entry.Path), RevisionAction.Modify, null)); + foreach (var entry in changes.TypeChanged) + paths.Add (new RevisionPath (rev.GitRepository.FromGitPath (entry.Path), RevisionAction.Modify, null)); + return paths.ToArray (); } @@ -264,21 +370,19 @@ namespace MonoDevelop.VersionControl.Git // Used for checking if we will dupe data. // This way we reduce the number of GitRevisions created and RevWalks done. - Dictionary<NGit.Repository, GitRevision> versionInfoCacheRevision = new Dictionary<NGit.Repository, GitRevision> (); - Dictionary<NGit.Repository, GitRevision> versionInfoCacheEmptyRevision = new Dictionary<NGit.Repository, GitRevision> (); + Dictionary<LibGit2Sharp.Repository, GitRevision> versionInfoCacheRevision = new Dictionary<LibGit2Sharp.Repository, GitRevision> (); + Dictionary<LibGit2Sharp.Repository, GitRevision> versionInfoCacheEmptyRevision = new Dictionary<LibGit2Sharp.Repository, GitRevision> (); VersionInfo[] GetDirectoryVersionInfo (FilePath localDirectory, IEnumerable<FilePath> localFileNames, bool getRemoteStatus, bool recursive) { - List<VersionInfo> versions = new List<VersionInfo> (); - HashSet<FilePath> existingFiles = new HashSet<FilePath> (); - HashSet<FilePath> nonVersionedMissingFiles = new HashSet<FilePath> (); - + var versions = new List<VersionInfo> (); + if (localFileNames != null) { var localFiles = new List<FilePath> (); foreach (var group in GroupByRepository (localFileNames)) { var repository = group.Key; GitRevision arev; if (!versionInfoCacheEmptyRevision.TryGetValue (repository, out arev)) { - arev = new GitRevision (this, repository, ""); + arev = new GitRevision (this, repository, null); versionInfoCacheEmptyRevision.Add (repository, arev); } foreach (var p in group) { @@ -286,108 +390,129 @@ namespace MonoDevelop.VersionControl.Git if (recursive) versions.AddRange (GetDirectoryVersionInfo (p, getRemoteStatus, true)); versions.Add (new VersionInfo (p, "", true, VersionStatus.Versioned, arev, VersionStatus.Versioned, null)); - } - else { + } else localFiles.Add (p); - if (File.Exists (p)) - existingFiles.Add (p.CanonicalPath); - else - nonVersionedMissingFiles.Add (p.CanonicalPath); - } } } // No files to check, we are done - if (localFiles.Count == 0) - return versions.ToArray (); - - localFileNames = localFiles; + if (localFiles.Count != 0) { + foreach (var group in GroupByRepository (localFileNames)) { + var repository = group.Key; + + GitRevision rev = null; + Commit headCommit = GetHeadCommit (repository); + if (headCommit != null) { + if (!versionInfoCacheRevision.TryGetValue (repository, out rev)) { + rev = new GitRevision (this, repository, headCommit); + versionInfoCacheRevision.Add (repository, rev); + } else if (rev.Commit != headCommit) { + rev = new GitRevision (this, repository, headCommit); + versionInfoCacheRevision [repository] = rev; + } + } + + GetFilesVersionInfoCore (repository, rev, group.ToList (), versions); + } + } } else { - List<FilePath> directories = new List<FilePath> (); - CollectFiles (existingFiles, directories, localDirectory, recursive); + var directories = new List<FilePath> (); + CollectFiles (directories, localDirectory, recursive); + + // Set directory items as Versioned. + GitRevision arev = null; foreach (var group in GroupByRepository (directories)) { var repository = group.Key; - GitRevision arev; if (!versionInfoCacheEmptyRevision.TryGetValue (repository, out arev)) { - arev = new GitRevision (this, repository, ""); + arev = new GitRevision (this, repository, null); versionInfoCacheEmptyRevision.Add (repository, arev); } foreach (var p in group) versions.Add (new VersionInfo (p, "", true, VersionStatus.Versioned, arev, VersionStatus.Versioned, null)); } - } - IEnumerable<FilePath> paths; - if (localFileNames == null) { - if (recursive) { - paths = new [] { localDirectory }; - } else { - if (Directory.Exists (localDirectory)) - paths = Directory.GetFiles (localDirectory).Select (f => (FilePath)f); - else - paths = new FilePath [0]; + Commit headCommit = GetHeadCommit (RootRepository); + if (headCommit != null) { + if (!versionInfoCacheRevision.TryGetValue (RootRepository, out arev)) { + arev = new GitRevision (this, RootRepository, headCommit); + versionInfoCacheRevision.Add (RootRepository, arev); + } else if (arev.Commit != headCommit) { + arev = new GitRevision (this, RootRepository, headCommit); + versionInfoCacheRevision [RootRepository] = arev; + } } - } else { - paths = localFileNames; + + GetDirectoryVersionInfoCore (RootRepository, arev, localDirectory.CanonicalPath, versions, recursive); } - foreach (var group in GroupByRepository (paths)) { - var repository = group.Key; + return versions.ToArray (); + } - GitRevision rev = null; - RevCommit headCommit = GetHeadCommit (repository); - if (headCommit != null) { - if (!versionInfoCacheRevision.TryGetValue (repository, out rev)) { - rev = new GitRevision (this, repository, headCommit.Id.Name); - versionInfoCacheRevision.Add (repository, rev); - } else if (rev.ToString () != headCommit.Id.Name) { - rev = new GitRevision (this, repository, headCommit.Id.Name); - versionInfoCacheRevision [repository] = rev; - } + static void GetFilesVersionInfoCore (LibGit2Sharp.Repository repo, GitRevision rev, List<FilePath> localPaths, List<VersionInfo> versions) + { + foreach (var file in repo.ToGitPath (localPaths)) { + var status = repo.RetrieveStatus (file); + VersionStatus fstatus = VersionStatus.Versioned; + + if (status != FileStatus.Unaltered) { + if ((status & FileStatus.Added) != 0) + fstatus |= VersionStatus.ScheduledAdd; + else if ((status & (FileStatus.Removed | FileStatus.Missing)) != 0) + fstatus |= VersionStatus.ScheduledDelete; + else if ((status & (FileStatus.TypeChanged | FileStatus.Modified)) != 0) + fstatus |= VersionStatus.Modified; + else if ((status & (FileStatus.RenamedInIndex | FileStatus.RenamedInWorkDir)) != 0) + fstatus |= VersionStatus.ScheduledReplace; + else if ((status & (FileStatus.Nonexistent | FileStatus.Untracked)) != 0) + fstatus = VersionStatus.Unversioned; + else if ((status & FileStatus.Ignored) != 0) + fstatus = VersionStatus.Ignored; } - GetDirectoryVersionInfoCore (repository, rev, group, existingFiles, nonVersionedMissingFiles, versions); - - // Existing files for which git did not report a status are supposed to be tracked - foreach (FilePath file in existingFiles.Where (f => group.Contains (f))) { - VersionInfo vi = new VersionInfo (file, "", false, VersionStatus.Versioned, rev, VersionStatus.Versioned, null); - versions.Add (vi); - } + if (repo.Index.Conflicts [file] != null) + fstatus = VersionStatus.Versioned | VersionStatus.Conflicted; + + versions.Add (new VersionInfo (repo.FromGitPath (file), "", false, fstatus, rev, fstatus == VersionStatus.Ignored ? VersionStatus.Unversioned : VersionStatus.Versioned, null)); } + } + static void GetDirectoryVersionInfoCore (LibGit2Sharp.Repository repo, GitRevision rev, FilePath directory, List<VersionInfo> versions, bool recursive) + { + var relativePath = repo.ToGitPath (directory); + var status = repo.RetrieveStatus (new StatusOptions { + PathSpec = relativePath != "." ? new [] { relativePath } : null, + IncludeUnaltered = true, + }); - // Non existing files for which git did not report an status are unversioned - foreach (FilePath file in nonVersionedMissingFiles) - versions.Add (VersionInfo.CreateUnversioned (file, false)); + versions.AddRange (status.Added.Select (s => new VersionInfo ( + repo.FromGitPath (s.FilePath), "", false, VersionStatus.Versioned | VersionStatus.ScheduledAdd, rev, VersionStatus.Versioned, null))); + versions.AddRange (status.Ignored.Select (s => new VersionInfo ( + repo.FromGitPath (s.FilePath), "", false, VersionStatus.Ignored, rev, VersionStatus.Unversioned, null))); + versions.AddRange (status.Missing.Select (s => new VersionInfo ( + repo.FromGitPath (s.FilePath), "", false, VersionStatus.Versioned | VersionStatus.ScheduledDelete, rev, VersionStatus.Versioned, null))); + versions.AddRange (status.Modified.Select (s => new VersionInfo ( + repo.FromGitPath (s.FilePath), "", false, VersionStatus.Versioned | VersionStatus.Modified, rev, VersionStatus.Versioned, null))); + versions.AddRange (status.Removed.Select (s => new VersionInfo ( + repo.FromGitPath (s.FilePath), "", false, VersionStatus.Versioned | VersionStatus.ScheduledDelete, rev, VersionStatus.Versioned, null))); + versions.AddRange (status.RenamedInIndex.Select (s => new VersionInfo ( + repo.FromGitPath (s.FilePath), "", false, VersionStatus.Versioned | VersionStatus.ScheduledReplace, rev, VersionStatus.Versioned, null))); + versions.AddRange (status.RenamedInWorkDir.Select (s => new VersionInfo ( + repo.FromGitPath (s.FilePath), "", false, VersionStatus.Versioned | VersionStatus.ScheduledReplace, rev, VersionStatus.Versioned, null))); + versions.AddRange (status.Unaltered.Select (s => new VersionInfo ( + repo.FromGitPath (s.FilePath), "", false, VersionStatus.Versioned, rev, VersionStatus.Versioned, null))); + versions.AddRange (status.Untracked.Select (s => new VersionInfo ( + repo.FromGitPath (s.FilePath), "", false, VersionStatus.Unversioned, rev, VersionStatus.Unversioned, null))); + + foreach (var conflict in repo.Index.Conflicts) { + FilePath path = conflict.Ours.Path; + if (path.IsChildPathOf (directory)) + versions.Add (new VersionInfo ( + repo.FromGitPath (path), "", false, VersionStatus.Versioned | VersionStatus.Conflicted, rev, VersionStatus.Versioned, null)); + } - return versions.ToArray (); + if (!recursive) + versions.RemoveAll (v => v.LocalPath.ParentDirectory != directory); } - static void GetDirectoryVersionInfoCore (NGit.Repository repository, GitRevision rev, IEnumerable<FilePath> localPaths, HashSet<FilePath> existingFiles, HashSet<FilePath> nonVersionedMissingFiles, List<VersionInfo> versions) - { - var filteredStatus = new FilteredStatus (repository, repository.ToGitPath (localPaths)); - var status = filteredStatus.Call (); - HashSet<string> added = new HashSet<string> (); - Action<IEnumerable<string>, VersionStatus> AddFiles = delegate (IEnumerable<string> files, VersionStatus fstatus) { - foreach (string file in files) { - if (!added.Add (file)) - continue; - FilePath statFile = repository.FromGitPath (file); - existingFiles.Remove (statFile.CanonicalPath); - nonVersionedMissingFiles.Remove (statFile.CanonicalPath); - versions.Add (new VersionInfo (statFile, "", false, fstatus, rev, fstatus == VersionStatus.Ignored ? VersionStatus.Unversioned : VersionStatus.Versioned, null)); - } - }; - - AddFiles (status.GetAdded (), VersionStatus.Versioned | VersionStatus.ScheduledAdd); - AddFiles (status.GetChanged (), VersionStatus.Versioned | VersionStatus.Modified); - AddFiles (status.GetModified (), VersionStatus.Versioned | VersionStatus.Modified); - AddFiles (status.GetRemoved (), VersionStatus.Versioned | VersionStatus.ScheduledDelete); - AddFiles (status.GetMissing (), VersionStatus.Versioned | VersionStatus.ScheduledDelete); - AddFiles (status.GetConflicting (), VersionStatus.Versioned | VersionStatus.Conflicted); - AddFiles (status.GetUntracked (), VersionStatus.Unversioned); - AddFiles (filteredStatus.GetIgnoredNotInIndex (), VersionStatus.Ignored); - } - protected override VersionControlOperation GetSupportedOperations (VersionInfo vinfo) { VersionControlOperation ops = base.GetSupportedOperations (vinfo); @@ -395,387 +520,252 @@ namespace MonoDevelop.VersionControl.Git ops &= ~VersionControlOperation.Update; if (vinfo.IsVersioned && !vinfo.IsDirectory) ops |= VersionControlOperation.Annotate; + if (!vinfo.IsVersioned && vinfo.IsDirectory) + ops &= ~VersionControlOperation.Add; return ops; } - static void CollectFiles (HashSet<FilePath> files, List<FilePath> directories, FilePath dir, bool recursive) + static void CollectFiles (List<FilePath> directories, FilePath dir, bool recursive) { if (!Directory.Exists (dir)) return; directories.AddRange (Directory.GetDirectories (dir, "*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly) .Select (f => new FilePath (f))); - - files.UnionWith (Directory.GetFiles (dir, "*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly) - .Select (f => new FilePath (f).CanonicalPath)); } protected override Repository OnPublish (string serverPath, FilePath localPath, FilePath[] files, string message, ProgressMonitor monitor) { // Initialize the repository - RootRepository = GitUtil.Init (localPath, Url); - NGit.Api.Git git = new NGit.Api.Git (RootRepository); - try { - var refs = git.Fetch ().Call ().GetAdvertisedRefs (); - if (refs.Count > 0) { - throw new UserException ("The remote repository already contains branches. Publishing is only possible to an empty repository"); - } - } catch { - try { - RootRepository.Close (); - } catch { - - } - if (Directory.Exists (RootRepository.Directory)) - Directory.Delete (RootRepository.Directory, true); - RootRepository = null; - throw; - } - + RootRepository = new LibGit2Sharp.Repository (LibGit2Sharp.Repository.Init (localPath)); RootPath = localPath; + RootRepository.Network.Remotes.Add ("origin", Url); + // Add the project files ChangeSet cs = CreateChangeSet (localPath); - var cmd = git.Add (); foreach (FilePath fp in files) { - cmd.AddFilepattern (RootRepository.ToGitPath (fp)); + RootRepository.Stage (RootRepository.ToGitPath (fp)); cs.AddFile (fp); } - cmd.Call (); - + // Create the initial commit cs.GlobalComment = message; Commit (cs, monitor); - // Push to remote repo - Push (monitor, "origin", "master"); + RootRepository.Branches.Update (RootRepository.Branches ["master"], branch => branch.TrackedBranch = "refs/remotes/origin/master"); + + RetryUntilSuccess (monitor, delegate { + RootRepository.Network.Push (RootRepository.Head, new PushOptions { + OnPushStatusError = delegate (PushStatusError e) { + RootRepository.Dispose (); + RootRepository = null; + if (RootPath.Combine (".git").IsDirectory) + Directory.Delete (RootPath.Combine (".git"), true); + throw new UserException (e.Message); + }, + CredentialsProvider = GitCredentials.TryGet + }); + }); return this; } - + protected override void OnUpdate (FilePath[] localPaths, bool recurse, ProgressMonitor monitor) { - IEnumerable<DiffEntry> statusList = null; - + // TODO: Make it work differently for submodules. monitor.BeginTask (GettextCatalog.GetString ("Updating"), 5); - // Fetch remote commits - Fetch (monitor); - string upstreamRef = GitUtil.GetUpstreamSource (RootRepository, GetCurrentBranch ()); - if (upstreamRef == null) - upstreamRef = GetCurrentRemote () + "/" + GetCurrentBranch (); + if (RootRepository.Head.IsTracking) { + Fetch (monitor, RootRepository.Head.Remote.Name); - GitUpdateOptions options = GitService.StashUnstashWhenUpdating ? GitUpdateOptions.NormalUpdate : GitUpdateOptions.UpdateSubmodules; - if (GitService.UseRebaseOptionWhenPulling) - Rebase (upstreamRef, options, monitor); - else - Merge (upstreamRef, options, monitor); + GitUpdateOptions options = GitService.StashUnstashWhenUpdating ? GitUpdateOptions.NormalUpdate : GitUpdateOptions.UpdateSubmodules; + if (GitService.UseRebaseOptionWhenPulling) + Rebase (RootRepository.Head.TrackedBranch.Name, options, monitor); + else + Merge (RootRepository.Head.TrackedBranch.Name, options, monitor); + + monitor.Step (1); + } - monitor.Step (1); - - // Notify changes - if (statusList != null) - NotifyFileChanges (monitor, statusList); - monitor.EndTask (); } - public void Fetch (ProgressMonitor monitor) + static void RetryUntilSuccess (ProgressMonitor monitor, Action func) { - string remote = GetCurrentRemote (); - if (remote == null) - throw new InvalidOperationException ("No remotes defined"); + bool retry; + do { + try { + func (); + GitCredentials.StoreCredentials (); + retry = false; + } catch (AuthenticationException) { + GitCredentials.InvalidateCredentials (); + retry = true; + } catch (VersionControlException e) { + GitCredentials.InvalidateCredentials (); + if (monitor != null) + monitor.ReportError (e.Message, null); + retry = false; + } catch (UserCancelledException) { + GitCredentials.StoreCredentials (); + retry = false; + } catch (LibGit2SharpException e) { + GitCredentials.InvalidateCredentials (); + if (monitor != null) + monitor.ReportError (e.Message, null); + retry = false; + } + } while (retry); + } + public void Fetch (ProgressMonitor monitor, string remote) + { monitor.Log.WriteLine (GettextCatalog.GetString ("Fetching from '{0}'", remote)); - var fetch = new NGit.Api.Git (RootRepository).Fetch (); - using (var gm = new GitMonitor (monitor)) { - fetch.SetRemote (remote); - fetch.SetProgressMonitor (gm); - fetch.Call (); - } + int progress = 0; + RetryUntilSuccess (monitor, delegate { + RootRepository.Fetch (remote, new FetchOptions { + CredentialsProvider = GitCredentials.TryGet, + OnTransferProgress = (tp) => OnTransferProgress (tp, monitor, ref progress), + }); + }); monitor.Step (1); } - bool GetSubmodulesToUpdate (List<string> updateSubmodules) + bool CommonPreMergeRebase (GitUpdateOptions options, ProgressMonitor monitor, out int stashIndex) { - List<string> dirtySubmodules = new List<string> (); - - // Iterate submodules and do status. - // SubmoduleStatus does not report changes for dirty submodules. - foreach (var submodule in CachedSubmodules) { - var submoduleGit = new NGit.Api.Git (submodule); - var statusCommand = submoduleGit.Status (); - var status = statusCommand.Call (); + stashIndex = -1; + monitor.Step (1); - if (status.IsClean ()) - updateSubmodules.Add (RootRepository.ToGitPath (submodule.WorkTree.GetAbsolutePath ())); - else - dirtySubmodules.Add (RootRepository.ToGitPath (submodule.WorkTree.GetAbsolutePath ())); + if ((options & GitUpdateOptions.SaveLocalChanges) != GitUpdateOptions.SaveLocalChanges) { + const VersionStatus unclean = VersionStatus.Modified | VersionStatus.ScheduledAdd | VersionStatus.ScheduledDelete; + bool modified = false; + if (GetDirectoryVersionInfo (RootPath, false, true).Any (v => (v.Status & unclean) != VersionStatus.Unversioned)) + modified = true; + + if (modified) { + if (MessageService.GenericAlert ( + MonoDevelop.Ide.Gui.Stock.Question, + GettextCatalog.GetString ("You have uncommitted changes"), + GettextCatalog.GetString ("What do you want to do?"), + AlertButton.Cancel, + new AlertButton ("Stash")) == AlertButton.Cancel) + return false; + + options |= GitUpdateOptions.SaveLocalChanges; + } } - - if (dirtySubmodules.Count != 0) { - StringBuilder submodules = new StringBuilder (Environment.NewLine + Environment.NewLine); - foreach (var item in dirtySubmodules) - submodules.AppendLine (item); - - AlertButton response = MessageService.GenericAlert ( - MonoDevelop.Ide.Gui.Stock.Question, - GettextCatalog.GetString ("You have local changes in the submodules below"), - GettextCatalog.GetString ("Do you want continue? Detached HEADs will have their changes lost.{0}", submodules.ToString ()), - new AlertButton[] { - AlertButton.No, - new AlertButton ("Only unchanged"), - AlertButton.Yes - } - ); - - if (response == AlertButton.No) + if ((options & GitUpdateOptions.SaveLocalChanges) == GitUpdateOptions.SaveLocalChanges) { + monitor.Log.WriteLine (GettextCatalog.GetString ("Saving local changes")); + Stash stash; + if (!TryCreateStash (monitor, GetStashName ("_tmp_"), out stash)) return false; - if (response == AlertButton.Yes) - updateSubmodules.AddRange (dirtySubmodules); + if (stash != null) + stashIndex = 0; + monitor.Step (1); } return true; } - public void Rebase (string upstreamRef, GitUpdateOptions options, ProgressMonitor monitor) + void ConflictResolver(ProgressMonitor monitor, Commit resetToIfFail, string message) { - StashCollection stashes = GitUtil.GetStashes (RootRepository); - Stash stash = null; - NGit.Api.Git git = new NGit.Api.Git (RootRepository); - try - { - monitor.BeginTask (GettextCatalog.GetString ("Rebasing"), 5); - List<string> UpdateSubmodules = new List<string> (); - - // TODO: Fix stash so we don't have to do update before the main repo update. - if ((options & GitUpdateOptions.UpdateSubmodules) == GitUpdateOptions.UpdateSubmodules) { - monitor.Log.WriteLine (GettextCatalog.GetString ("Checking repository submodules")); - if (!GetSubmodulesToUpdate (UpdateSubmodules)) - return; - - monitor.Log.WriteLine (GettextCatalog.GetString ("Updating repository submodules")); - var submoduleUpdate = git.SubmoduleUpdate (); - foreach (var submodule in UpdateSubmodules) - submoduleUpdate.AddPath (submodule); - - submoduleUpdate.Call (); - monitor.Step (1); - } - - if ((options & GitUpdateOptions.SaveLocalChanges) != GitUpdateOptions.SaveLocalChanges) { - const VersionStatus unclean = VersionStatus.Modified | VersionStatus.ScheduledAdd | VersionStatus.ScheduledDelete; - bool modified = false; - if (GetDirectoryVersionInfo (RootPath, false, true).Any (v => (v.Status & unclean) != VersionStatus.Unversioned)) - modified = true; - - if (modified) { - if (MessageService.GenericAlert ( - MonoDevelop.Ide.Gui.Stock.Question, - GettextCatalog.GetString ("You have uncommitted changes"), - GettextCatalog.GetString ("What do you want to do?"), - AlertButton.Cancel, - new AlertButton ("Stash")) == AlertButton.Cancel) - return; - - options |= GitUpdateOptions.SaveLocalChanges; - } + bool commit = true; + foreach (var conflictFile in RootRepository.Index.Conflicts) { + ConflictResult res = ResolveConflict (RootRepository.FromGitPath (conflictFile.Ancestor.Path)); + if (res == ConflictResult.Abort) { + RootRepository.Reset (ResetMode.Hard, resetToIfFail); + commit = false; + break; } - - if ((options & GitUpdateOptions.SaveLocalChanges) == GitUpdateOptions.SaveLocalChanges) { - monitor.Log.WriteLine (GettextCatalog.GetString ("Saving local changes")); - using (var gm = new GitMonitor (monitor)) - stash = stashes.Create (gm, GetStashName ("_tmp_")); - monitor.Step (1); + if (res == ConflictResult.Skip) { + Revert (RootRepository.FromGitPath (conflictFile.Ancestor.Path), false, monitor); + break; } + } + if (commit) + RootRepository.Commit (message); + } - RebaseCommand rebase = git.Rebase (); - rebase.SetOperation (RebaseCommand.Operation.BEGIN); - rebase.SetUpstream (upstreamRef); - var gmonitor = new GitMonitor (monitor); - rebase.SetProgressMonitor (gmonitor); - - bool aborted = false; - - try { - var result = rebase.Call (); - while (!aborted && result.GetStatus () == RebaseResult.Status.STOPPED) { - rebase = git.Rebase (); - rebase.SetProgressMonitor (gmonitor); - rebase.SetOperation (RebaseCommand.Operation.CONTINUE); - bool commitChanges = true; - var conflicts = GitUtil.GetConflictedFiles (RootRepository); - foreach (string conflictFile in conflicts) { - ConflictResult res = ResolveConflict (RootRepository.FromGitPath (conflictFile)); - if (res == ConflictResult.Abort) { - aborted = true; - commitChanges = false; - rebase.SetOperation (RebaseCommand.Operation.ABORT); - break; - } else if (res == ConflictResult.Skip) { - rebase.SetOperation (RebaseCommand.Operation.SKIP); - commitChanges = false; - break; - } - } - if (commitChanges) { - NGit.Api.AddCommand cmd = git.Add (); - foreach (string conflictFile in conflicts) - cmd.AddFilepattern (conflictFile); - cmd.Call (); - } - result = rebase.Call (); - } - - if ((options & GitUpdateOptions.UpdateSubmodules) == GitUpdateOptions.UpdateSubmodules) { - monitor.Log.WriteLine (GettextCatalog.GetString ("Updating repository submodules")); - var submoduleUpdate = git.SubmoduleUpdate (); - foreach (var submodule in UpdateSubmodules) - submoduleUpdate.AddPath (submodule); + void CommonPostMergeRebase(int stashIndex, GitUpdateOptions options, ProgressMonitor monitor) + { + if ((options & GitUpdateOptions.SaveLocalChanges) == GitUpdateOptions.SaveLocalChanges) { + monitor.Step (1); - submoduleUpdate.Call (); - } - } catch { - if (!aborted) { - rebase = git.Rebase (); - rebase.SetOperation (RebaseCommand.Operation.ABORT); - rebase.SetProgressMonitor (gmonitor); - rebase.Call (); - } - throw; - } finally { - gmonitor.Dispose (); - } - - } finally { - if ((options & GitUpdateOptions.SaveLocalChanges) == GitUpdateOptions.SaveLocalChanges) - monitor.Step (1); - // Restore local changes - if (stash != null) { + if (stashIndex != -1) { monitor.Log.WriteLine (GettextCatalog.GetString ("Restoring local changes")); - using (var gm = new GitMonitor (monitor)) - stash.Apply (gm); - stashes.Remove (stash); + PopStash (monitor, stashIndex); + monitor.Step (1); } - monitor.EndTask (); } + monitor.EndTask (); } - public void Merge (string branch, GitUpdateOptions options, ProgressMonitor monitor) + public void Rebase (string branch, GitUpdateOptions options, ProgressMonitor monitor) { - IEnumerable<DiffEntry> statusList = null; - Stash stash = null; - StashCollection stashes = GetStashes (RootRepository); - NGit.Api.Git git = new NGit.Api.Git (RootRepository); - + int stashIndex = -1; try { - monitor.BeginTask (GettextCatalog.GetString ("Merging"), 5); - List<string> UpdateSubmodules = new List<string> (); - - // TODO: Fix stash so we don't have to do update before the main repo update. - if ((options & GitUpdateOptions.UpdateSubmodules) == GitUpdateOptions.UpdateSubmodules) { - monitor.Log.WriteLine (GettextCatalog.GetString ("Checking repository submodules")); - if (!GetSubmodulesToUpdate (UpdateSubmodules)) - return; - - monitor.Log.WriteLine (GettextCatalog.GetString ("Updating repository submodules")); - var submoduleUpdate = git.SubmoduleUpdate (); - foreach (var submodule in UpdateSubmodules) - submoduleUpdate.AddPath (submodule); - - submoduleUpdate.Call (); - monitor.Step (1); + monitor.BeginTask (GettextCatalog.GetString ("Rebasing"), 5); + if (!CommonPreMergeRebase (options, monitor, out stashIndex)) + return; + + // Do a rebase. + var divergence = RootRepository.ObjectDatabase.CalculateHistoryDivergence (RootRepository.Head.Tip, RootRepository.Branches [branch].Tip); + var toApply = RootRepository.Commits.QueryBy (new CommitFilter { + Since = RootRepository.Head.Tip, + Until = divergence.CommonAncestor, + SortBy = CommitSortStrategies.Topological + }); + + RootRepository.Reset (ResetMode.Hard, divergence.Another); + + int count = toApply.Count (); + int i = 1; + foreach (var com in toApply) { + monitor.Log.WriteLine ("Cherry-picking {0} - {1}/{2}", com.Id, i, count); + CherryPickResult cherryRes = RootRepository.CherryPick (com, com.Author, new CherryPickOptions { + CheckoutNotifyFlags = refreshFlags, + OnCheckoutNotify = RefreshFile, + }); + if (cherryRes.Status == CherryPickStatus.Conflicts) + ConflictResolver(monitor, toApply.Last(), RootRepository.Info.Message ?? com.Message); + ++i; } + } finally { + CommonPostMergeRebase (stashIndex, options, monitor); + } + } - // Get a list of files that are different in the target branch - statusList = GitUtil.GetChangedFiles (RootRepository, branch); - monitor.Step (1); + public void Merge (string branch, GitUpdateOptions options, ProgressMonitor monitor) + { + int stashIndex = -1; - if ((options & GitUpdateOptions.SaveLocalChanges) != GitUpdateOptions.SaveLocalChanges) { - const VersionStatus unclean = VersionStatus.Modified | VersionStatus.ScheduledAdd | VersionStatus.ScheduledDelete; - bool modified = false; - if (GetDirectoryVersionInfo (RootPath, false, true).Any (v => (v.Status & unclean) != VersionStatus.Unversioned)) - modified = true; - - if (modified) { - if (MessageService.GenericAlert ( - MonoDevelop.Ide.Gui.Stock.Question, - GettextCatalog.GetString ("You have uncommitted changes"), - GettextCatalog.GetString ("What do you want to do?"), - AlertButton.Cancel, - new AlertButton ("Stash")) == AlertButton.Cancel) - return; - - options |= GitUpdateOptions.SaveLocalChanges; - } - } + Signature sig = GetSignature (); + if (sig == null) + return; - if ((options & GitUpdateOptions.SaveLocalChanges) == GitUpdateOptions.SaveLocalChanges) { - monitor.Log.WriteLine (GettextCatalog.GetString ("Saving local changes")); - using (var gm = new GitMonitor (monitor)) - stash = stashes.Create (gm, GetStashName ("_tmp_")); - monitor.Step (1); - } - - // Apply changes - - ObjectId branchId = RootRepository.Resolve (branch); - - MergeCommandResult mergeResult = git.Merge ().SetStrategy (MergeStrategy.RESOLVE).Include (branchId).Call (); - if (mergeResult.GetMergeStatus () == MergeStatus.CONFLICTING || mergeResult.GetMergeStatus () == MergeStatus.FAILED) { - var conflicts = mergeResult.GetConflicts (); - bool commit = true; - if (conflicts != null) { - foreach (string conflictFile in conflicts.Keys) { - ConflictResult res = ResolveConflict (RootRepository.FromGitPath (conflictFile)); - if (res == ConflictResult.Abort) { - GitUtil.HardReset (RootRepository, GetHeadCommit (RootRepository)); - commit = false; - break; - } else if (res == ConflictResult.Skip) { - Revert (RootRepository.FromGitPath (conflictFile), false, monitor); - break; - } - } - } - if (commit) - git.Commit ().Call (); - } + try { + monitor.BeginTask (GettextCatalog.GetString ("Merging"), 5); + CommonPreMergeRebase (options, monitor, out stashIndex); - if ((options & GitUpdateOptions.UpdateSubmodules) == GitUpdateOptions.UpdateSubmodules) { - monitor.Log.WriteLine (GettextCatalog.GetString ("Updating repository submodules")); - var submoduleUpdate = git.SubmoduleUpdate (); - foreach (var submodule in UpdateSubmodules) - submoduleUpdate.AddPath (submodule); + // Do a merge. + MergeResult mergeResult = RootRepository.Merge (branch, sig, new MergeOptions { + CheckoutNotifyFlags = refreshFlags, + OnCheckoutNotify = RefreshFile, + }); - submoduleUpdate.Call (); - monitor.Step (1); - } + if (mergeResult.Status == MergeStatus.Conflicts) + ConflictResolver (monitor, RootRepository.Head.Tip, RootRepository.Info.Message); } finally { - if ((options & GitUpdateOptions.SaveLocalChanges) == GitUpdateOptions.SaveLocalChanges) - monitor.Step (1); - - // Restore local changes - if (stash != null) { - monitor.Log.WriteLine (GettextCatalog.GetString ("Restoring local changes")); - using (var gm = new GitMonitor (monitor)) - stash.Apply (gm); - stashes.Remove (stash); - monitor.Step (1); - } - monitor.EndTask (); + CommonPostMergeRebase (stashIndex, GitUpdateOptions.SaveLocalChanges, monitor); } - - // Notify changes - if (statusList != null) - NotifyFileChanges (monitor, statusList); } static ConflictResult ResolveConflict (string file) { ConflictResult res = ConflictResult.Abort; DispatchService.GuiSyncDispatch (delegate { - ConflictResolutionDialog dlg = new ConflictResolutionDialog (); + var dlg = new ConflictResolutionDialog (); try { dlg.Load (file); var dres = (Gtk.ResponseType) MessageService.RunCustomDialog (dlg); @@ -804,203 +794,119 @@ namespace MonoDevelop.VersionControl.Git string message = changeSet.GlobalComment; if (string.IsNullOrEmpty (message)) throw new ArgumentException ("Commit message must not be null or empty!", "message"); - - NGit.Api.Git git = new NGit.Api.Git (RootRepository); - NGit.Api.CommitCommand commit = git.Commit (); - commit.SetMessage (message); - if (changeSet.ExtendedProperties.Contains ("Git.AuthorName")) { - commit.SetAuthor ((string)changeSet.ExtendedProperties ["Git.AuthorName"], (string)changeSet.ExtendedProperties ["Git.AuthorEmail"]); - } - - foreach (string path in GetFilesInPaths (changeSet.Items.Select (i => i.LocalPath))) - commit.SetOnly (path); - - commit.Call (); - } - - List<string> GetFilesInPaths (IEnumerable<FilePath> paths) - { - // Expand directory paths into file paths. Convert paths to full paths. - List<string> filePaths = new List<string> (); - foreach (var path in paths) { - DirectoryInfo dir = new DirectoryInfo (path); - if (dir.Exists) - filePaths.AddRange (GetDirectoryFiles (dir)); - else - filePaths.Add (RootRepository.ToGitPath (path)); - } - return filePaths; - } - - IEnumerable<string> GetDirectoryFiles (DirectoryInfo dir) - { - FileTreeIterator iter = new FileTreeIterator (dir.FullName, RootRepository.FileSystem, WorkingTreeOptions.KEY.Parse(RootRepository.GetConfig())); - while (!iter.Eof) { - var file = iter.GetEntryFile (); - if (file != null && !iter.IsEntryIgnored ()) - yield return file.GetPath (); - iter.Next (1); - } + Signature sig = GetSignature (); + if (sig == null) + return; + + var repo = (GitRepository)changeSet.Repository; + repo.RootRepository.Stage (changeSet.Items.Select (i => i.LocalPath).ToPathStrings ()); + + if (changeSet.ExtendedProperties.Contains ("Git.AuthorName")) + repo.RootRepository.Commit (message, new Signature ( + (string)changeSet.ExtendedProperties ["Git.AuthorName"], + (string)changeSet.ExtendedProperties ["Git.AuthorEmail"], + DateTimeOffset.Now), sig); + else + repo.RootRepository.Commit (message, sig); } public bool IsUserInfoDefault () { - UserConfig config = RootRepository.GetConfig ().Get (UserConfig.KEY); - return config.IsCommitterNameImplicit () && config.IsCommitterEmailImplicit (); + string name; + string email; + try { + name = RootRepository.Config.Get<string> ("user.name").Value; + email = RootRepository.Config.Get<string> ("user.email").Value; + } catch { + name = email = null; + } + return name == null && email == null; } - + public void GetUserInfo (out string name, out string email) { - UserConfig config = RootRepository.GetConfig ().Get (UserConfig.KEY); - name = config.GetCommitterName (); - email = config.GetCommitterEmail (); + try { + name = RootRepository.Config.Get<string> ("user.name").Value; + email = RootRepository.Config.Get<string> ("user.email").Value; + } catch { + string dlgName = null, dlgEmail = null; + + DispatchService.GuiSyncDispatch (() => { + var dlg = new UserGitConfigDialog (); + try { + if ((Gtk.ResponseType)MessageService.RunCustomDialog (dlg) == Gtk.ResponseType.Ok) { + dlgName = dlg.UserText; + dlgEmail = dlg.EmailText; + SetUserInfo (dlgName, dlgEmail); + } + } finally { + dlg.Destroy (); + } + }); + + name = dlgName; + email = dlgEmail; + } } public void SetUserInfo (string name, string email) { - StoredConfig config = RootRepository.GetConfig (); - config.SetString ("user", null, "name", name); - config.SetString ("user", null, "email", email); - config.Save (); + RootRepository.Config.Set ("user.name", name); + RootRepository.Config.Set ("user.email", email); } protected override void OnCheckout (FilePath targetLocalPath, Revision rev, bool recurse, ProgressMonitor monitor) { - CloneCommand cmd = NGit.Api.Git.CloneRepository (); - cmd.SetURI (Url); - cmd.SetRemote ("origin"); - cmd.SetBranch ("refs/heads/master"); - cmd.SetDirectory ((string)targetLocalPath); - cmd.SetCloneSubmodules (true); - using (var gm = new GitMonitor (monitor, 4)) { - cmd.SetProgressMonitor (gm); - try { - cmd.Call (); - } catch (NGit.Api.Errors.JGitInternalException e) { - // We cancelled and NGit throws. - // Or URL is wrong. - if (e.InnerException is NGit.Errors.MissingObjectException || - e.InnerException is NGit.Errors.TransportException || - e.InnerException is NGit.Errors.NotSupportedException) { - FileService.DeleteDirectory (targetLocalPath); - throw new VersionControlException (e.InnerException.Message); - } - } - } + int transferProgress = 0; + int checkoutProgress = 0; + RetryUntilSuccess (monitor, delegate { + RootPath = LibGit2Sharp.Repository.Clone (Url, targetLocalPath, new CloneOptions { + CredentialsProvider = GitCredentials.TryGet, + + OnTransferProgress = (tp) => OnTransferProgress (tp, monitor, ref transferProgress), + OnCheckoutProgress = (path, completedSteps, totalSteps) => OnCheckoutProgress (completedSteps, totalSteps, monitor, ref checkoutProgress), + }); + }); + + if (monitor.CancellationToken.IsCancellationRequested) + return; + + RootPath = RootPath.ParentDirectory; + RootRepository = new LibGit2Sharp.Repository (RootPath); } protected override void OnRevert (FilePath[] localPaths, bool recurse, ProgressMonitor monitor) { - // Replace with NGit.Api.Git.Reset () - - // FIXME: we lack info about what happened to files - - var groups = GroupByRepository (localPaths).ToArray (); - monitor.BeginTask (GettextCatalog.GetString ("Reverting files"), groups.Length); - - foreach (var group in groups) { - monitor.BeginStep (1); + foreach (var group in GroupByRepository (localPaths)) { var repository = group.Key; - var files = group.ToArray (); - - var c = GetHeadCommit (repository); - RevTree tree = c != null ? c.Tree : null; - - List<FilePath> changedFiles = new List<FilePath> (); - List<FilePath> removedFiles = new List<FilePath> (); - - monitor.BeginTask (files.Length); - - DirCache dc = repository.LockDirCache (); - DirCacheBuilder builder = dc.Builder (); - - try { - HashSet<string> entriesToRemove = new HashSet<string> (); - HashSet<string> foldersToRemove = new HashSet<string> (); - - // Add the new entries - foreach (FilePath fp in files) { - string p = repository.ToGitPath (fp); - - // Register entries to be removed from the index - if (Directory.Exists (fp)) - foldersToRemove.Add (p); + HashSet<FilePath> files = new HashSet<FilePath> (); + + foreach (var item in group) + if (item.IsDirectory) { + foreach (var vi in GetDirectoryVersionInfo (item, false, recurse)) + if (!vi.IsDirectory) + files.Add (vi.LocalPath); + } else + files.Add (item); + + monitor.BeginTask (GettextCatalog.GetString ("Reverting files"), 1); + + int progress = 0; + repository.CheckoutPaths ("HEAD", repository.ToGitPath (files), new CheckoutOptions { + OnCheckoutProgress = (path, completedSteps, totalSteps) => OnCheckoutProgress (completedSteps, totalSteps, monitor, ref progress), + CheckoutModifiers = CheckoutModifiers.Force, + CheckoutNotifyFlags = refreshFlags, + OnCheckoutNotify = delegate (string path, CheckoutNotifyFlags notifyFlags) { + if ((notifyFlags & CheckoutNotifyFlags.Untracked) != 0) + FileService.NotifyFileRemoved (repository.FromGitPath (path)); else - entriesToRemove.Add (p); - - TreeWalk tw = tree != null ? TreeWalk.ForPath (repository, p, tree) : null; - if (tw == null) { - // Removed from the index - } - else { - // Add new entries - - TreeWalk r; - if (tw.IsSubtree) { - // It's a directory. Make sure we remove existing index entries of this directory - foldersToRemove.Add (p); - - // We have to iterate through all folder files. We need a new iterator since the - // existing rw is not recursive - r = new TreeWalk(repository); - r.Reset (tree); - r.Filter = PathFilterGroup.CreateFromStrings(new string[]{p}); - r.Recursive = true; - r.Next (); - } else { - r = tw; - } - - do { - // There can be more than one entry if reverting a whole directory - string rpath = repository.FromGitPath (r.PathString); - DirCacheEntry e = new DirCacheEntry (r.PathString); - e.SetObjectId (r.GetObjectId (0)); - e.FileMode = r.GetFileMode (0); - if (!Directory.Exists (Path.GetDirectoryName (rpath))) - Directory.CreateDirectory (rpath); - DirCacheCheckout.CheckoutEntry (repository, rpath, e); - builder.Add (e); - changedFiles.Add (rpath); - } while (r.Next ()); - } - } - - // Add entries we want to keep - int count = dc.GetEntryCount (); - for (int n=0; n<count; n++) { - DirCacheEntry e = dc.GetEntry (n); - string path = e.PathString; - if (!entriesToRemove.Contains (path) && !foldersToRemove.Any (f => IsSubpath (f,path))) - builder.Add (e); + RefreshFile (path, notifyFlags); + return true; } - - builder.Commit (); - monitor.Step (1); - } - catch { - dc.Unlock (); - throw; - } - - foreach (FilePath p in changedFiles) - FileService.NotifyFileChanged (p, true); - - foreach (FilePath p in removedFiles) - FileService.NotifyFileRemoved (p); - + }); monitor.EndTask (); } - monitor.EndTask (); - } - - static bool IsSubpath (string basePath, string childPath) - { - // FIXME: use FilePath? - if (basePath [basePath.Length - 1] == '/') - return childPath.StartsWith (basePath, StringComparison.InvariantCulture); - return childPath.StartsWith (basePath + "/", StringComparison.InvariantCulture); } protected override void OnRevertRevision (FilePath localPath, Revision revision, ProgressMonitor monitor) @@ -1010,35 +916,22 @@ namespace MonoDevelop.VersionControl.Git protected override void OnRevertToRevision (FilePath localPath, Revision revision, ProgressMonitor monitor) { - NGit.Repository repo = GetRepository (localPath); - NGit.Api.Git git = new NGit.Api.Git (repo); - GitRevision gitRev = (GitRevision)revision; - - // Rewrite file data from selected revision. - foreach (var path in GetFilesInPaths (new [] { localPath })) - MonoDevelop.Projects.Text.TextFile.WriteFile (repo.FromGitPath (path), GetCommitTextContent (gitRev.Commit, path), null); - - monitor.ReportSuccess (GettextCatalog.GetString ("Successfully reverted {0} to revision {1}", localPath, gitRev)); + throw new NotSupportedException (); } - protected override void OnAdd (FilePath[] localPaths, bool recurse, ProgressMonitor monitor) { foreach (var group in GroupByRepository (localPaths)) { var repository = group.Key; - var files = group; - - NGit.Api.Git git = new NGit.Api.Git (repository); - var cmd = git.Add (); - foreach (FilePath fp in files) - cmd.AddFilepattern (repository.ToGitPath (fp)); - cmd.Call (); + var files = group.Where (f => !f.IsDirectory); + if (files.Any ()) + repository.Stage (repository.ToGitPath (files)); } } protected override void OnDeleteFiles (FilePath[] localPaths, bool force, ProgressMonitor monitor, bool keepLocal) { - DeleteCore (localPaths, force, monitor, keepLocal); + DeleteCore (localPaths, keepLocal); foreach (var path in localPaths) { if (keepLocal) { @@ -1058,7 +951,7 @@ namespace MonoDevelop.VersionControl.Git protected override void OnDeleteDirectories (FilePath[] localPaths, bool force, ProgressMonitor monitor, bool keepLocal) { - DeleteCore (localPaths, force, monitor, keepLocal); + DeleteCore (localPaths, keepLocal); foreach (var path in localPaths) { if (keepLocal) { @@ -1066,7 +959,7 @@ namespace MonoDevelop.VersionControl.Git foreach (var info in GetDirectoryVersionInfo (path, false, true)) { if (info != null && info.HasLocalChange (VersionStatus.ScheduledAdd)) { // Revert addition. - Revert (path, false, monitor); + Revert (path, true, monitor); } } } else { @@ -1078,81 +971,48 @@ namespace MonoDevelop.VersionControl.Git } } - void DeleteCore (FilePath[] localPaths, bool force, ProgressMonitor monitor, bool keepLocal) + void DeleteCore (FilePath[] localPaths, bool keepLocal) { foreach (var group in GroupByRepository (localPaths)) { - List<FilePath> backupFiles = new List<FilePath> (); - var repository = group.Key; - var files = group; - - var git = new NGit.Api.Git (repository); - RmCommand rm = git.Rm (); - foreach (var f in files) { - // Create backups. - if (keepLocal) { - string newPath = ""; - if (f.IsDirectory) { - newPath = FileService.CreateTempDirectory (); - FileService.CopyDirectory (f, newPath); - } else { - newPath = Path.GetTempFileName (); - File.Copy (f, newPath, true); - } - backupFiles.Add (newPath); + if (!keepLocal) + foreach (var f in localPaths) { + if (File.Exists (f)) + File.Delete (f); + else if (Directory.Exists (f)) + Directory.Delete (f, true); } - rm.AddFilepattern (repository.ToGitPath (f)); - } + var repository = group.Key; + var files = repository.ToGitPath (group); - try { - rm.Call (); - } finally { - // Restore backups. - if (keepLocal) { - foreach (var backup in backupFiles) { - if (backup.IsDirectory) - FileService.MoveDirectory (backup, files.ElementAt (backupFiles.IndexOf (backup))); - else - File.Move (backup, files.ElementAt (backupFiles.IndexOf (backup))); - } - } - } + repository.Remove (files, !keepLocal); } } protected override string OnGetTextAtRevision (FilePath repositoryPath, Revision revision) { - var repository = GetRepository (repositoryPath); - ObjectId id = repository.Resolve (revision.ToString ()); - RevWalk rw = new RevWalk (repository); - RevCommit c = rw.ParseCommit (id); - return c == null ? string.Empty : GetCommitTextContent (c, repositoryPath); + var gitRev = (GitRevision)revision; + var blob = (Blob)gitRev.Commit [gitRev.GitRepository.ToGitPath (repositoryPath)].Target; + return blob.GetContentText (); } public override DiffInfo GenerateDiff (FilePath baseLocalPath, VersionInfo versionInfo) { try { - var repository = GetRepository (baseLocalPath); - if ((versionInfo.Status & VersionStatus.ScheduledAdd) != 0) { - var ctxt = GetFileContent (versionInfo.LocalPath); - return new DiffInfo (baseLocalPath, versionInfo.LocalPath, GenerateDiff (EmptyContent, ctxt, repository)); - } else if ((versionInfo.Status & VersionStatus.ScheduledDelete) != 0) { - var ctxt = GetCommitContent (GetHeadCommit (repository), versionInfo.LocalPath); - return new DiffInfo (baseLocalPath, versionInfo.LocalPath, GenerateDiff (ctxt, EmptyContent, repository)); - } else if ((versionInfo.Status & VersionStatus.Modified) != 0 || (versionInfo.Status & VersionStatus.Conflicted) != 0) { - var ctxt1 = GetCommitContent (GetHeadCommit (repository), versionInfo.LocalPath); - var ctxt2 = GetFileContent (versionInfo.LocalPath); - return new DiffInfo (baseLocalPath, versionInfo.LocalPath, GenerateDiff (ctxt1, ctxt2, repository)); - } + var repository = GetRepository (versionInfo.LocalPath); + var patch = repository.Diff.Compare<Patch> (new [] { repository.ToGitPath (versionInfo.LocalPath) }); + // Trim the header by taking out the first 2 lines. + int diffStart = patch.Content.IndexOf ('\n', patch.Content.IndexOf ('\n') + 1); + return new DiffInfo (baseLocalPath, versionInfo.LocalPath, patch.Content.Substring (diffStart + 1)); } catch (Exception ex) { LoggingService.LogError ("Could not get diff for file '" + versionInfo.LocalPath + "'", ex); } - return null; + return null; } - + public override DiffInfo[] PathDiff (FilePath baseLocalPath, FilePath[] localPaths, bool remoteDiff) { - List<DiffInfo> diffs = new List<DiffInfo> (); + var diffs = new List<DiffInfo> (); VersionInfo[] vinfos = GetDirectoryVersionInfo (baseLocalPath, localPaths, false, true); foreach (VersionInfo vi in vinfos) { var diff = GenerateDiff (baseLocalPath, vi); @@ -1161,340 +1021,253 @@ namespace MonoDevelop.VersionControl.Git } return diffs.ToArray (); } - - static byte[] GetFileContent (string file) - { - return File.ReadAllBytes (file); - } - byte[] GetCommitContent (RevCommit c, FilePath file) + byte[] GetCommitContent (Commit c, FilePath file) { var repository = GetRepository (file); - TreeWalk tw = TreeWalk.ForPath (repository, file.IsAbsolute ? repository.ToGitPath (file) : (string)file, c.Tree); - if (tw == null) - return EmptyContent; - ObjectId id = tw.GetObjectId (0); - return repository.ObjectDatabase.Open (id).GetBytes (); - } - - string GetCommitTextContent (RevCommit c, FilePath file) - { - var content = GetCommitContent (c, file); - if (RawText.IsBinary (content)) - return String.Empty; - return Mono.TextEditor.Utils.TextFileUtility.GetText (content); - } - - static string GenerateDiff (byte[] data1, byte[] data2, NGit.Repository repo) - { - if (RawText.IsBinary (data1) || RawText.IsBinary (data2)) { - if (data1.Length != data2.Length) - return GettextCatalog.GetString (" Binary files differ"); - if (data1.Length == data2.Length) { - for (int n=0; n<data1.Length; n++) { - if (data1[n] != data2[n]) - return GettextCatalog.GetString (" Binary files differ"); - } - } - return string.Empty; + var blob = (Blob)c [repository.ToGitPath (file)].Target; + using (var stream = blob.GetContentStream ()) + using (var ms = new MemoryStream ()) { + stream.CopyTo (ms); + return ms.ToArray (); } - var text1 = new RawText (data1); - var text2 = new RawText (data2); + } - var edits = DiffAlgorithm.GetAlgorithm (DiffAlgorithm.SupportedAlgorithm.MYERS) - .Diff (RawTextComparator.DEFAULT, text1, text2); - MemoryStream s = new MemoryStream (); - var formatter = new DiffFormatter (s); - formatter.SetRepository (repo); - formatter.Format (edits, text1, text2); - return Encoding.UTF8.GetString (s.ToArray ()); + string GetCommitTextContent (Commit c, FilePath file) + { + var repository = GetRepository (file); + var blob = (Blob)c [repository.ToGitPath (file)].Target; + return blob.IsBinary ? String.Empty : blob.GetContentText (); } public string GetCurrentRemote () { - List<string> remotes = new List<string> (GetRemotes ().Select (r => r.Name)); + var remotes = new List<string> (GetRemotes ().Select (r => r.Name)); if (remotes.Count == 0) return null; - - if (remotes.Contains ("origin")) - return "origin"; - return remotes[0]; + return remotes.Contains ("origin") ? "origin" : remotes [0]; } public void Push (ProgressMonitor monitor, string remote, string remoteBranch) { - string remoteRef = "refs/heads/" + remoteBranch; - IEnumerable<PushResult> res; - - var push = new NGit.Api.Git (RootRepository).Push (); - - // We only have one pushed branch. - push.SetRemote (remote).SetRefSpecs (new RefSpec (remoteRef)); - using (var gm = new GitMonitor (monitor)) { - push.SetProgressMonitor (gm); + bool success = true; - try { - res = push.Call (); - } catch (NGit.Api.Errors.JGitInternalException e) { - if (e.InnerException is NGit.Errors.TransportException) - throw new VersionControlException (e.InnerException.Message); - throw; - } + var branch = RootRepository.Head; + if (branch.TrackedBranch == null) { + RootRepository.Branches.Update (branch, b => b.TrackedBranch = "refs/remotes/" + remote + "/" + remoteBranch); } - foreach (var pr in res) { - var remoteUpdate = pr.GetRemoteUpdate (remoteRef); - - switch (remoteUpdate.GetStatus ()) { - case RemoteRefUpdate.Status.UP_TO_DATE: monitor.ReportSuccess (GettextCatalog.GetString ("Remote branch is up to date.")); break; - case RemoteRefUpdate.Status.REJECTED_NODELETE: monitor.ReportError (GettextCatalog.GetString ("The server is configured to deny deletion of the branch"), null); break; - case RemoteRefUpdate.Status.REJECTED_NONFASTFORWARD: monitor.ReportError (GettextCatalog.GetString ("The update is a non-fast-forward update. Merge the remote changes before pushing again."), null); break; - case RemoteRefUpdate.Status.OK: - monitor.ReportSuccess (GettextCatalog.GetString ("Push operation successfully completed.")); - // Update the remote branch - ObjectId headId = remoteUpdate.GetNewObjectId (); - RefUpdate updateRef = RootRepository.UpdateRef (Constants.R_REMOTES + remote + "/" + remoteBranch); - updateRef.SetNewObjectId(headId); - updateRef.Update(); - break; - default: - string msg = remoteUpdate.GetMessage (); - msg = !string.IsNullOrEmpty (msg) ? msg : GettextCatalog.GetString ("Push operation failed"); - monitor.ReportError (msg, null); - break; - } - } + RetryUntilSuccess (monitor, () => + RootRepository.Network.Push (RootRepository.Network.Remotes [remote], "refs/heads/" + remoteBranch, new PushOptions { + OnPushStatusError = delegate (PushStatusError pushStatusErrors) { + LoggingService.LogWarning ("Failed to Push to {0}. Message was \"{1}\".", pushStatusErrors.Reference, pushStatusErrors.Message); + string message; + // TODO: Remove me when libgit2 merges https://github.com/libgit2/libgit2/pull/3129 and we update binaries. + if (string.Equals (pushStatusErrors.Message, "early EOF", StringComparison.OrdinalIgnoreCase)) + message = "Server connection has been reset. Please retry pushing."; + else + message = pushStatusErrors.Message; + + monitor.ReportError (message, null); + success = false; + }, + CredentialsProvider = GitCredentials.TryGet + }) + ); + + if (!success) + return; + + monitor.ReportSuccess (GettextCatalog.GetString ("Push operation successfully completed.")); } - public void CreateBranchFromCommit (string name, RevCommit id) + public void CreateBranchFromCommit (string name, Commit id) { - var create = new NGit.Api.Git (RootRepository).BranchCreate (); - if (id != null) - create.SetStartPoint (id); - create.SetName (name); - create.Call (); + RootRepository.Branches.Add (name, id); } public void CreateBranch (string name, string trackSource) { - var create = new NGit.Api.Git (RootRepository).BranchCreate (); - if (!String.IsNullOrEmpty (trackSource)) - create.SetStartPoint (trackSource); - create.SetName (name); - create.Call (); + RootRepository.Branches.Update (RootRepository.Branches.Add (name, RootRepository.Head.Tip), + bu => bu.Remote = trackSource); } public void SetBranchTrackSource (string name, string trackSource) { - GitUtil.SetUpstreamSource (RootRepository, name, trackSource); + var branch = RootRepository.Branches [name]; + if (branch != null) { + RootRepository.Branches.Update (branch, bu => bu.TrackedBranch = trackSource); + } else + RootRepository.Branches.Add (name, trackSource); } public void RemoveBranch (string name) { - var git = new NGit.Api.Git (RootRepository); - git.BranchDelete ().SetBranchNames (name).SetForce (true).Call (); + RootRepository.Branches.Remove (name); } public void RenameBranch (string name, string newName) { - var git = new NGit.Api.Git (RootRepository); - git.BranchRename ().SetOldName (name).SetNewName (newName).Call (); + RootRepository.Branches.Rename (name, newName, true); } - public IEnumerable<RemoteSource> GetRemotes () + public IEnumerable<Remote> GetRemotes () { - StoredConfig cfg = RootRepository.GetConfig (); - foreach (RemoteConfig rc in RemoteConfig.GetAllRemoteConfigs (cfg)) - yield return new RemoteSource (cfg, rc); + return RootRepository.Network.Remotes; } - + public bool IsBranchMerged (string branchName) { // check if a branch is merged into HEAD - RevWalk walk = new RevWalk(RootRepository); - RevCommit tip = walk.ParseCommit(RootRepository.Resolve(Constants.HEAD)); - Ref currentRef = RootRepository.GetRef(branchName); - if (currentRef == null) - return true; - RevCommit @base = walk.ParseCommit(RootRepository.Resolve(branchName)); - return walk.IsMergedInto(@base, tip); + var tip = RootRepository.Branches [branchName].Tip.Sha; + return RootRepository.Commits.Any (c => c.Sha == tip); } public void RenameRemote (string name, string newName) { - StoredConfig cfg = RootRepository.GetConfig (); - RemoteConfig rem = RemoteConfig.GetAllRemoteConfigs (cfg).FirstOrDefault (r => r.Name == name); - if (rem != null) { - rem.Name = newName; - rem.Update (cfg); - } + RootRepository.Network.Remotes.Rename (name, newName); } - public void AddRemote (RemoteSource remote, bool importTags) + public void ChangeRemoteUrl (string name, string url) { - if (string.IsNullOrEmpty (remote.Name)) - throw new InvalidOperationException ("Name not set"); - - StoredConfig c = RootRepository.GetConfig (); - RemoteConfig rc = new RemoteConfig (c, remote.Name); - c.Save (); - remote.RepoRemote = rc; - remote.cfg = c; - UpdateRemote (remote); + RootRepository.Network.Remotes.Update ( + RootRepository.Network.Remotes [name], + r => r.Url = url + ); } - public void UpdateRemote (RemoteSource remote) + public void ChangeRemotePushUrl (string name, string url) { - if (string.IsNullOrEmpty (remote.FetchUrl)) - throw new InvalidOperationException ("Fetch url can't be empty"); - - if (remote.RepoRemote == null) - throw new InvalidOperationException ("Remote not created"); - - remote.Update (); - remote.cfg.Save (); + RootRepository.Network.Remotes.Update ( + RootRepository.Network.Remotes [name], + r => r.PushUrl = url + ); + } + + public void AddRemote (string name, string url, bool importTags) + { + if (string.IsNullOrEmpty (name)) + throw new InvalidOperationException ("Name not set"); + + RootRepository.Network.Remotes.Update (RootRepository.Network.Remotes.Add (name, url), + r => r.TagFetchMode = importTags ? TagFetchMode.All : TagFetchMode.Auto); } public void RemoveRemote (string name) { - StoredConfig cfg = RootRepository.GetConfig (); - RemoteConfig rem = RemoteConfig.GetAllRemoteConfigs (cfg).FirstOrDefault (r => r.Name == name); - if (rem != null) { - cfg.UnsetSection ("remote", name); - cfg.Save (); - } + RootRepository.Network.Remotes.Remove (name); } public IEnumerable<Branch> GetBranches () { - var list = new NGit.Api.Git (RootRepository).BranchList ().SetListMode (ListBranchCommand.ListMode.HEAD); - foreach (var item in list.Call ()) { - string name = NGit.Repository.ShortenRefName (item.GetName ()); - Branch br = new Branch (); - br.Name = name; - br.Tracking = GitUtil.GetUpstreamSource (RootRepository, name); - yield return br; - } + return RootRepository.Branches.Where (b => !b.IsRemote); } public IEnumerable<string> GetTags () { - var list = new NGit.Api.Git (RootRepository).TagList (); - foreach (var item in list.Call ()) { - string name = NGit.Repository.ShortenRefName (item.GetName ()); - yield return name; - } + return RootRepository.Tags.Select (t => t.Name); } public void AddTag (string name, Revision rev, string message) { - var addTag = new NGit.Api.Git (RootRepository).Tag (); - var gitRev = (GitRevision)rev; + Signature sig = GetSignature (); + if (sig == null) + return; - addTag.SetName (name).SetMessage (message).SetObjectId (gitRev.Commit); - addTag.SetObjectId (gitRev.Commit).SetTagger (new PersonIdent (RootRepository)); - addTag.Call (); + var gitRev = (GitRevision)rev; + RootRepository.Tags.Add (name, gitRev.Commit, sig, message); } public void RemoveTag (string name) { - var deleteTag = new NGit.Api.Git (RootRepository).TagDelete (); - deleteTag.SetTags (name).Call (); + RootRepository.Tags.Remove (name); } - public void PushAllTags () + public void PushTag (string name) { - var pushTags = new NGit.Api.Git (RootRepository).Push (); - pushTags.SetPushTags ().Call (); + RetryUntilSuccess (null, delegate { + RootRepository.Network.Push (RootRepository.Network.Remotes [GetCurrentRemote ()], "refs/tags/" + name + ":refs/tags/" + name, new PushOptions { + CredentialsProvider = GitCredentials.TryGet, + }); + }); } public IEnumerable<string> GetRemoteBranches (string remoteName) { - var list = new NGit.Api.Git (RootRepository).BranchList ().SetListMode (ListBranchCommand.ListMode.REMOTE); - foreach (var item in list.Call ()) { - string name = NGit.Repository.ShortenRefName (item.GetName ()); - if (name.StartsWith (remoteName + "/", StringComparison.Ordinal)) - yield return name.Substring (remoteName.Length + 1); - } + return RootRepository.Branches.Where (b => b.IsRemote && b.Remote.Name == remoteName).Select (b => b.Name.Substring (b.Name.IndexOf ('/') + 1)); } public string GetCurrentBranch () { - return RootRepository.GetBranch (); + return RootRepository.Head.Name; } public void SwitchToBranch (ProgressMonitor monitor, string branch) { + Signature sig = GetSignature (); + Stash stash; + int stashIndex = -1; + if (sig == null) + return; + monitor.BeginTask (GettextCatalog.GetString ("Switching to branch {0}", branch), GitService.StashUnstashWhenSwitchingBranches ? 4 : 2); - + // Get a list of files that are different in the target branch - IEnumerable<DiffEntry> statusList = GitUtil.GetChangedFiles (RootRepository, branch); - - StashCollection stashes = null; - Stash stash = null; - + var statusList = GitUtil.GetChangedFiles (RootRepository, branch); + if (GitService.StashUnstashWhenSwitchingBranches) { - stashes = GitUtil.GetStashes (RootRepository); - // Remove the stash for this branch, if exists string currentBranch = GetCurrentBranch (); - stash = GetStashForBranch (stashes, currentBranch); - if (stash != null) - stashes.Remove (stash); + stashIndex = GetStashForBranch (RootRepository.Stashes, currentBranch); + if (stashIndex != -1) + RootRepository.Stashes.Remove (stashIndex); + + if (!TryCreateStash (monitor, GetStashName (currentBranch), out stash)) + return; - // Create a new stash for the branch. This allows switching branches - // without losing local changes - using (var gm = new GitMonitor (monitor)) - stash = stashes.Create (gm, GetStashName (currentBranch)); - monitor.Step (1); } - // Replace with NGit.Api.Git ().Checkout () - // Switch to the target branch - var checkout = new NGit.Api.Git (RootRepository).Checkout (); - checkout.SetName (branch); try { - checkout.Call (); + int progress = 0; + RootRepository.Checkout (branch, new CheckoutOptions { + OnCheckoutProgress = (path, completedSteps, totalSteps) => OnCheckoutProgress (completedSteps, totalSteps, monitor, ref progress), + OnCheckoutNotify = RefreshFile, + CheckoutNotifyFlags = refreshFlags, + }); } finally { // Restore the branch stash if (GitService.StashUnstashWhenSwitchingBranches) { - stash = GetStashForBranch (stashes, branch); - if (stash != null) { - using (var gm = new GitMonitor (monitor)) - stash.Apply (gm); - stashes.Remove (stash); - } + stashIndex = GetStashForBranch (RootRepository.Stashes, branch); + if (stashIndex != -1) + PopStash (monitor, stashIndex); monitor.Step (1); } } // Notify file changes - NotifyFileChanges (monitor, statusList); - + if (BranchSelectionChanged != null) BranchSelectionChanged (this, EventArgs.Empty); - + monitor.EndTask (); } - void NotifyFileChanges (ProgressMonitor monitor, IEnumerable<DiffEntry> statusList) + void NotifyFileChanges (ProgressMonitor monitor, TreeChanges statusList) { - List<DiffEntry> changes = new List<DiffEntry> (statusList); - // Files added to source branch not present to target branch. - var removed = changes.Where (c => c.GetChangeType () == DiffEntry.ChangeType.ADD).Select (c => GetRepository (c.GetNewPath ()).FromGitPath (c.GetNewPath ())).ToList (); - var modified = changes.Where (c => c.GetChangeType () != DiffEntry.ChangeType.ADD).Select (c => GetRepository (c.GetNewPath ()).FromGitPath (c.GetNewPath ())).ToList (); - + var removed = statusList.Where (c => c.Status == ChangeKind.Added).Select (c => GetRepository (c.Path).FromGitPath (c.Path)).ToList (); + var modified = statusList.Where (c => c.Status != ChangeKind.Added).Select (c => GetRepository (c.Path).FromGitPath (c.Path)).ToList (); + monitor.BeginTask (GettextCatalog.GetString ("Updating solution"), removed.Count + modified.Count); FileService.NotifyFilesChanged (modified, true); monitor.Step (modified.Count); - + FileService.NotifyFilesRemoved (removed); monitor.Step (removed.Count); - + monitor.EndTask (); } @@ -1502,48 +1275,48 @@ namespace MonoDevelop.VersionControl.Git { return "__MD_" + branchName; } - + public static string GetStashBranchName (string stashName) { - if (stashName.StartsWith ("__MD_", StringComparison.Ordinal)) - return stashName.Substring (5); - - return null; + return stashName.StartsWith ("__MD_", StringComparison.Ordinal) ? stashName.Substring (5) : null; } - static Stash GetStashForBranch (StashCollection stashes, string branchName) + static int GetStashForBranch (StashCollection stashes, string branchName) { string sn = GetStashName (branchName); - foreach (Stash ss in stashes) { - if (ss.Comment.IndexOf (sn, StringComparison.InvariantCulture) != -1) - return ss; + int count = stashes.Count (); + for (int i = 0; i < count; ++i) { + if (stashes[i].Message.IndexOf (sn, StringComparison.InvariantCulture) != -1) + return i; } - return null; + return -1; } public ChangeSet GetPushChangeSet (string remote, string branch) { ChangeSet cset = CreateChangeSet (RootPath); - ObjectId cid1 = RootRepository.Resolve (remote + "/" + branch); - ObjectId cid2 = RootRepository.Resolve (RootRepository.GetBranch ()); - RevWalk rw = new RevWalk (RootRepository); - RevCommit c1 = rw.ParseCommit (cid1); - RevCommit c2 = rw.ParseCommit (cid2); - - foreach (var change in GitUtil.CompareCommits (RootRepository, c1, c2)) { + + Commit reference = RootRepository.Branches [remote + "/" + branch].Tip; + Commit compared = RootRepository.Head.Tip; + + foreach (var change in GitUtil.CompareCommits (RootRepository, reference, compared)) { VersionStatus status; - switch (change.GetChangeType ()) { - case DiffEntry.ChangeType.ADD: + switch (change.Status) { + case ChangeKind.Added: + case ChangeKind.Copied: status = VersionStatus.ScheduledAdd; break; - case DiffEntry.ChangeType.DELETE: + case ChangeKind.Deleted: status = VersionStatus.ScheduledDelete; break; + case ChangeKind.Renamed: + status = VersionStatus.ScheduledReplace; + break; default: status = VersionStatus.Modified; break; } - VersionInfo vi = new VersionInfo (RootRepository.FromGitPath (change.GetNewPath ()), "", false, status | VersionStatus.Versioned, null, VersionStatus.Versioned, null); + var vi = new VersionInfo (RootRepository.FromGitPath (change.Path), "", false, status | VersionStatus.Versioned, null, VersionStatus.Versioned, null); cset.AddFile (vi); } return cset; @@ -1551,28 +1324,23 @@ namespace MonoDevelop.VersionControl.Git public DiffInfo[] GetPushDiff (string remote, string branch) { - ObjectId cid1 = RootRepository.Resolve (remote + "/" + branch); - ObjectId cid2 = RootRepository.Resolve (RootRepository.GetBranch ()); - RevWalk rw = new RevWalk (RootRepository); - RevCommit c1 = rw.ParseCommit (cid1); - RevCommit c2 = rw.ParseCommit (cid2); - - List<DiffInfo> diffs = new List<DiffInfo> (); - foreach (var change in GitUtil.CompareCommits (RootRepository, c1, c2)) { - string diff; - switch (change.GetChangeType ()) { - case DiffEntry.ChangeType.DELETE: - diff = GenerateDiff (GetCommitContent (c2, change.GetOldPath ()), EmptyContent, RootRepository); - break; - case DiffEntry.ChangeType.ADD: - diff = GenerateDiff (EmptyContent, GetCommitContent (c1, change.GetNewPath ()), RootRepository); + Commit reference = RootRepository.Branches[remote + "/" + branch].Tip; + Commit compared = RootRepository.Head.Tip; + + var diffs = new List<DiffInfo> (); + var patch = RootRepository.Diff.Compare<Patch> (reference.Tree, compared.Tree); + foreach (var change in GitUtil.CompareCommits (RootRepository, reference, compared)) { + string path; + switch (change.Status) { + case ChangeKind.Deleted: + case ChangeKind.Renamed: + path = change.OldPath; break; default: - diff = GenerateDiff (GetCommitContent (c1, change.GetNewPath ()), GetCommitContent (c2, change.GetNewPath ()), RootRepository); + path = change.Path; break; } - DiffInfo di = new DiffInfo (RootPath, RootRepository.FromGitPath (change.GetNewPath ()), diff); - diffs.Add (di); + diffs.Add (new DiffInfo (RootPath, RootRepository.FromGitPath (path), patch[path].Patch)); } return diffs.ToArray (); } @@ -1584,11 +1352,13 @@ namespace MonoDevelop.VersionControl.Git base.OnMoveFile (localSrcPath, localDestPath, force, monitor); return; } - base.OnMoveFile (localSrcPath, localDestPath, force, monitor); - Add (localDestPath, false, monitor); - - if ((vi.Status & VersionStatus.ScheduledAdd) != 0) - Revert (localSrcPath, false, monitor); + + vi = GetVersionInfo (localDestPath, VersionInfoQueryFlags.IgnoreCache); + if (vi != null && ((vi.Status & (VersionStatus.ScheduledDelete | VersionStatus.ScheduledReplace)) != VersionStatus.Unversioned)) + RootRepository.Unstage (localDestPath); + + RootRepository.Move (localSrcPath, localDestPath); + ClearCachedVersionInfo (localSrcPath, localDestPath); } protected override void OnMoveDirectory (FilePath localSrcPath, FilePath localDestPath, bool force, ProgressMonitor monitor) @@ -1609,262 +1379,107 @@ namespace MonoDevelop.VersionControl.Git public override Annotation[] GetAnnotations (FilePath repositoryPath) { var repository = GetRepository (repositoryPath); - RevCommit hc = GetHeadCommit (repository); + Commit hc = GetHeadCommit (repository); if (hc == null) return new Annotation [0]; - var git = new NGit.Api.Git (repository); - var result = git.Blame ().SetFollowFileRenames (true).SetFilePath (repository.ToGitPath (repositoryPath)).Call (); - result.ComputeAll (); - - List<Annotation> list = new List<Annotation> (); - for (int i = 0; i < result.GetResultContents ().Size (); i++) { - var commit = result.GetSourceCommit (i); - var author = result.GetSourceAuthor (i); - if (commit != null && author != null) { - var commitTime = new DateTime (1970, 1, 1).AddSeconds (commit.CommitTime); - string authorName = author.GetName () ?? commit.GetAuthorIdent ().GetName (); - string email = author.GetEmailAddress () ?? commit.GetAuthorIdent ().GetEmailAddress (); - list.Add (new Annotation (commit.Name, authorName, commitTime, String.Format ("<{0}>", email))); - } else { - list.Add (new Annotation (GettextCatalog.GetString ("working copy"), "<uncommitted>", DateTime.Now)); - } + int lines = File.ReadAllLines (repositoryPath).Length; + var list = new List<Annotation> (lines); + var working = new Annotation (GettextCatalog.GetString ("working copy"), "<uncommitted>", DateTime.Now); + for (int i = 0; i < lines; ++i) + list.Add (working); + + foreach (var hunk in repository.Blame (repository.ToGitPath (repositoryPath))) { + var commit = hunk.FinalCommit; + var author = hunk.FinalSignature; + working = new Annotation (commit.Sha, author.Name, author.When.LocalDateTime, String.Format ("<{0}>", author.Email)); + for (int i = 0; i < hunk.LineCount; ++i) + list [hunk.FinalStartLineNumber + i] = working; } + return list.ToArray (); } - - internal GitRevision GetPreviousRevisionFor (GitRevision revision) - { - ObjectId id = revision.GitRepository.Resolve (revision + "^"); - if (id == null) - return null; - return new GitRevision (this, revision.GitRepository, id.Name); - } protected override void OnIgnore (FilePath[] localPath) { - List<FilePath> ignored = new List<FilePath> (); + var ignored = new List<FilePath> (); string gitignore = RootPath + Path.DirectorySeparatorChar + ".gitignore"; string txt; if (File.Exists (gitignore)) { - using (StreamReader br = new StreamReader (gitignore)) { + using (var br = new StreamReader (gitignore)) { while ((txt = br.ReadLine ()) != null) { ignored.Add (txt); } } } - StringBuilder sb = new StringBuilder (); + var sb = new StringBuilder (); foreach (var path in localPath.Except (ignored)) sb.AppendLine (RootRepository.ToGitPath (path)); File.AppendAllText (RootPath + Path.DirectorySeparatorChar + ".gitignore", sb.ToString ()); + RootRepository.Stage (".gitignore"); } protected override void OnUnignore (FilePath[] localPath) { - List<string> ignored = new List<string> (); + var ignored = new List<string> (); string gitignore = RootPath + Path.DirectorySeparatorChar + ".gitignore"; string txt; if (File.Exists (gitignore)) { - using (StreamReader br = new StreamReader (RootPath + Path.DirectorySeparatorChar + ".gitignore")) { + using (var br = new StreamReader (RootPath + Path.DirectorySeparatorChar + ".gitignore")) { while ((txt = br.ReadLine ()) != null) { ignored.Add (txt); } } } - StringBuilder sb = new StringBuilder (); + var sb = new StringBuilder (); foreach (var path in ignored.Except (RootRepository.ToGitPath (localPath))) sb.AppendLine (path); File.WriteAllText (RootPath + Path.DirectorySeparatorChar + ".gitignore", sb.ToString ()); + RootRepository.Stage (".gitignore"); } } - + public class GitRevision: Revision { readonly string rev; - - internal RevCommit Commit { get; set; } + internal Commit Commit { get; set; } internal FilePath FileForChanges { get; set; } - public NGit.Repository GitRepository { + public LibGit2Sharp.Repository GitRepository { get; private set; } - public GitRevision (Repository repo, NGit.Repository gitRepository, string rev) : base(repo) + public GitRevision (Repository repo, LibGit2Sharp.Repository gitRepository, Commit commit) : base(repo) { - this.rev = rev; GitRepository = gitRepository; + Commit = commit; + rev = Commit != null ? Commit.Id.Sha : ""; } - public GitRevision (Repository repo, NGit.Repository gitRepository, string rev, DateTime time, string author, string message) : base(repo, time, author, message) + public GitRevision (Repository repo, LibGit2Sharp.Repository gitRepository, Commit commit, DateTime time, string author, string message) : base(repo, time, author, message) { - this.rev = rev; GitRepository = gitRepository; + Commit = commit; + rev = Commit != null ? Commit.Id.Sha : ""; } public override string ToString () { return rev; } - + public override string ShortName { - get { - return rev.Length > 10 ? rev.Substring (0, 10) : rev; - } + get { return rev.Length > 10 ? rev.Substring (0, 10) : rev; } } public override Revision GetPrevious () { - return ((GitRepository) this.Repository).GetPreviousRevisionFor (this); - } - } - - public class Branch - { - public string Name { get; internal set; } - public string Tracking { get; internal set; } - } - - public class RemoteSource - { - internal RemoteConfig RepoRemote; - internal StoredConfig cfg; - - public RemoteSource () - { - } - - internal RemoteSource (StoredConfig cfg, RemoteConfig rem) - { - this.cfg = cfg; - RepoRemote = rem; - Name = rem.Name; - FetchUrl = rem.URIs.Select (u => u.ToString ()).FirstOrDefault (); - PushUrl = rem.PushURIs.Select (u => u.ToString ()).FirstOrDefault (); - if (string.IsNullOrEmpty (PushUrl)) - PushUrl = FetchUrl; - } - - internal void Update () - { - RepoRemote.Name = Name; - - var list = new List<URIish> (RepoRemote.URIs); - list.ForEach (u => RepoRemote.RemoveURI (u)); - - list = new List<URIish> (RepoRemote.PushURIs); - list.ForEach (u => RepoRemote.RemovePushURI (u)); - - RepoRemote.AddURI (new URIish (FetchUrl)); - if (!string.IsNullOrEmpty (PushUrl) && PushUrl != FetchUrl) - RepoRemote.AddPushURI (new URIish (PushUrl)); - RepoRemote.Update (cfg); - } - - public string Name { get; internal set; } - public string FetchUrl { get; internal set; } - public string PushUrl { get; internal set; } - } - - class GitMonitor: NGit.ProgressMonitor, IDisposable - { - readonly MonoDevelop.Core.ProgressMonitor monitor; - int currentWork; - int currentStep; - bool taskStarted; - int totalTasksOverride = -1; - bool monitorStarted; - - public GitMonitor (MonoDevelop.Core.ProgressMonitor monitor) - { - this.monitor = monitor; - } - - public GitMonitor (MonoDevelop.Core.ProgressMonitor monitor, int totalTasksOverride) - { - this.monitor = monitor; - this.totalTasksOverride = totalTasksOverride; - } - - public override void Start (int totalTasks) - { - monitorStarted = true; - currentStep = 0; - currentWork = totalTasksOverride != -1 ? totalTasksOverride : (totalTasks > 0 ? totalTasks : 1); - totalTasksOverride = -1; - monitor.BeginTask (null, currentWork); - } - - - public override void BeginTask (string title, int totalWork) - { - if (taskStarted) - EndTask (); - - taskStarted = true; - currentStep = 0; - currentWork = totalWork > 0 ? totalWork : 1; - monitor.BeginTask (title, currentWork); - } - - - public override void Update (int completed) - { - currentStep += completed; - if (currentStep >= (currentWork / 100)) { - monitor.Step (currentStep); - currentStep = 0; - } - } - - - public override void EndTask () - { - taskStarted = false; - monitor.EndTask (); - monitor.Step (1); - } - - - public override bool IsCancelled () - { - return monitor.CancellationToken.IsCancellationRequested; - } - - public void Dispose () - { - if (monitorStarted) - monitor.EndTask (); - } - } - - class LocalGitRepository: FileRepository - { - WeakReference dirCacheRef; - DateTime dirCacheTimestamp; - - public LocalGitRepository (string path): base (path) - { - } - - public override DirCache ReadDirCache () - { - DirCache dc = null; - if (dirCacheRef != null) - dc = dirCacheRef.Target as DirCache; - if (dc != null) { - DateTime wt = File.GetLastWriteTime (GetIndexFile ()); - if (wt == dirCacheTimestamp) - return dc; - } - dirCacheTimestamp = File.GetLastWriteTime (GetIndexFile ()); - dc = base.ReadDirCache (); - dirCacheRef = new WeakReference (dc); - return dc; + var id = Commit.Parents.FirstOrDefault (); + return id == null ? null : new GitRevision (Repository, GitRepository, id); } } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitSelectRevisionDialog.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitSelectRevisionDialog.cs index 58c888d866..779339b779 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitSelectRevisionDialog.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitSelectRevisionDialog.cs @@ -26,6 +26,7 @@ using System;
using MonoDevelop.Core;
using System.Text;
+using LibGit2Sharp; namespace MonoDevelop.VersionControl.Git
{
@@ -54,7 +55,7 @@ namespace MonoDevelop.VersionControl.Git var vbox = new Xwt.VBox ();
vbox.MinHeight = 400;
- vbox.MinWidth = 600;
+ vbox.MinWidth = 800;
vbox.PackStart(new Xwt.Label (GettextCatalog.GetString ("Tag Name")));
@@ -79,13 +80,26 @@ namespace MonoDevelop.VersionControl.Git revisionStore = new Xwt.ListStore (messageField, dateField, authorField, shaField, revisionField);
revisionList.DataSource = revisionStore;
- messageColumn = new Xwt.ListViewColumn (GettextCatalog.GetString ("Message"), new Xwt.TextCellView (messageField) { Ellipsize = Xwt.EllipsizeMode.End });
+ messageColumn = new Xwt.ListViewColumn (GettextCatalog.GetString ("Message"), new Xwt.TextCellView (messageField)) {
+ CanResize = true,
+ Alignment = Xwt.Alignment.Center,
+ };
+
revisionList.Columns.Add (messageColumn);
- dateColumn = new Xwt.ListViewColumn (GettextCatalog.GetString ("Date"), new Xwt.TextCellView (dateField));
+ dateColumn = new Xwt.ListViewColumn (GettextCatalog.GetString ("Date"), new Xwt.TextCellView (dateField)) {
+ CanResize = true,
+ Alignment = Xwt.Alignment.Center,
+ };
revisionList.Columns.Add (dateColumn);
- authorColumn = new Xwt.ListViewColumn (GettextCatalog.GetString ("Author"), new Xwt.TextCellView (authorField));
+ authorColumn = new Xwt.ListViewColumn (GettextCatalog.GetString ("Author"), new Xwt.TextCellView (authorField)) {
+ CanResize = true,
+ Alignment = Xwt.Alignment.Center,
+ };
revisionList.Columns.Add (authorColumn);
- shaColumn = new Xwt.ListViewColumn (GettextCatalog.GetString ("Revision"), new Xwt.TextCellView (shaField));
+ shaColumn = new Xwt.ListViewColumn (GettextCatalog.GetString ("Revision"), new Xwt.TextCellView (shaField)) {
+ CanResize = true,
+ Alignment = Xwt.Alignment.Center,
+ };
revisionList.Columns.Add (shaColumn);
var history = repo.GetHistory (repo.RootPath, null);
@@ -119,7 +133,7 @@ namespace MonoDevelop.VersionControl.Git void CheckSensitive ()
{
- if (!String.IsNullOrWhiteSpace (tagNameEntry.Text) && GitUtil.IsValidBranchName (tagNameEntry.Text) &&
+ if (!String.IsNullOrWhiteSpace (tagNameEntry.Text) && Reference.IsValidName ("refs/tags/" + tagNameEntry.Text) && revisionList.SelectedRow != -1) {
buttonOk.Sensitive = true;
return;
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitService.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitService.cs index 789a216ba4..cd69eb6a68 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitService.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitService.cs @@ -1,21 +1,21 @@ -// +// // GitService.cs -// +// // Author: // Lluis Sanchez Gual <lluis@novell.com> -// +// // Copyright (c) 2010 Novell, Inc (http://www.novell.com) -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -28,9 +28,9 @@ using System; using MonoDevelop.Core; using MonoDevelop.Ide; using MonoDevelop.Ide.ProgressMonitoring; -using NGit.Api; using System.Threading; using System.Threading.Tasks; +using LibGit2Sharp; namespace MonoDevelop.VersionControl.Git { @@ -41,29 +41,29 @@ namespace MonoDevelop.VersionControl.Git get { return PropertyService.Get ("MonoDevelop.VersionControl.Git.UseRebaseOptionWhenPulling", true); } set { PropertyService.Set ("MonoDevelop.VersionControl.Git.UseRebaseOptionWhenPulling", value); } } - + public static bool StashUnstashWhenUpdating { get { return PropertyService.Get ("MonoDevelop.VersionControl.Git.StashUnstashWhenUpdating", true); } set { PropertyService.Set ("MonoDevelop.VersionControl.Git.StashUnstashWhenUpdating", value); } } - + public static bool StashUnstashWhenSwitchingBranches { get { return PropertyService.Get ("MonoDevelop.VersionControl.Git.StashUnstashWhenSwitchingBranches", true); } set { PropertyService.Set ("MonoDevelop.VersionControl.Git.StashUnstashWhenSwitchingBranches", value); } } - + public static void Push (GitRepository repo) { var dlg = new PushDialog (repo); try { if (MessageService.RunCustomDialog (dlg) != (int) Gtk.ResponseType.Ok) return; - + string remote = dlg.SelectedRemote; string branch = dlg.SelectedRemoteBranch ?? repo.GetCurrentBranch (); - + ProgressMonitor monitor = VersionControlService.GetProgressMonitor (GettextCatalog.GetString ("Pushing changes..."), VersionControlOperationType.Push); ThreadPool.QueueUserWorkItem (delegate { try { @@ -78,29 +78,29 @@ namespace MonoDevelop.VersionControl.Git dlg.Destroy (); } } - + public static void ShowConfigurationDialog (GitRepository repo) { var dlg = new GitConfigurationDialog (repo); MessageService.ShowCustomDialog (dlg); } - + public static void ShowMergeDialog (GitRepository repo, bool rebasing) { - MergeDialog dlg = new MergeDialog (repo, rebasing); + var dlg = new MergeDialog (repo, rebasing); try { if (MessageService.RunCustomDialog (dlg) == (int) Gtk.ResponseType.Ok) { dlg.Hide (); if (rebasing) { using (ProgressMonitor monitor = VersionControlService.GetProgressMonitor (GettextCatalog.GetString ("Rebasing branch '{0}'...", dlg.SelectedBranch))) { if (dlg.IsRemote) - repo.Fetch (monitor); + repo.Fetch (monitor, dlg.RemoteName); repo.Rebase (dlg.SelectedBranch, dlg.StageChanges ? GitUpdateOptions.SaveLocalChanges : GitUpdateOptions.None, monitor); } } else { using (ProgressMonitor monitor = VersionControlService.GetProgressMonitor (GettextCatalog.GetString ("Merging branch '{0}'...", dlg.SelectedBranch))) { if (dlg.IsRemote) - repo.Fetch (monitor); + repo.Fetch (monitor, dlg.RemoteName); repo.Merge (dlg.SelectedBranch, dlg.StageChanges ? GitUpdateOptions.SaveLocalChanges : GitUpdateOptions.None, monitor); } } @@ -109,16 +109,16 @@ namespace MonoDevelop.VersionControl.Git dlg.Destroy (); } } - + public static void ShowStashManager (GitRepository repo) { - StashManagerDialog dlg = new StashManagerDialog (repo); + var dlg = new StashManagerDialog (repo); MessageService.ShowCustomDialog (dlg); } - + public async static void SwitchToBranch (GitRepository repo, string branch) { - MessageDialogProgressMonitor monitor = new MessageDialogProgressMonitor (true, false, false, true); + var monitor = new MessageDialogProgressMonitor (true, false, false, true); try { IdeApp.Workbench.AutoReloadDocuments = true; IdeApp.Workbench.LockGui (); @@ -136,20 +136,20 @@ namespace MonoDevelop.VersionControl.Git IdeApp.Workbench.UnlockGui (); } } - - public static Task ApplyStash (Stash s) + + public static Task<bool> ApplyStash (GitRepository repo, int s) { - MessageDialogProgressMonitor monitor = new MessageDialogProgressMonitor (true, false, false, true); + var monitor = new MessageDialogProgressMonitor (true, false, false, true); var statusTracker = IdeApp.Workspace.GetFileStatusTracker (); var t = Task.Run (delegate { try { - MergeCommandResult result; - using (var gm = new GitMonitor (monitor)) - result = s.Apply (gm); - ReportStashResult (monitor, result); + var res = repo.ApplyStash (monitor, s); + ReportStashResult (res); + return true; } catch (Exception ex) { string msg = GettextCatalog.GetString ("Stash operation failed."); monitor.ReportError (msg, ex); + return false; } finally { monitor.Dispose (); @@ -158,25 +158,10 @@ namespace MonoDevelop.VersionControl.Git }); return t; } - - public static void ReportStashResult (ProgressMonitor monitor, MergeCommandResult result) + + public static void ReportStashResult (StashApplyStatus status) { - if (result.GetMergeStatus () == MergeStatus.FAILED) { - string msg = GettextCatalog.GetString ("Stash operation failed."); - DispatchService.GuiDispatch (delegate { - IdeApp.Workbench.StatusBar.ShowWarning (msg); - }); - string txt = msg + "\n\n" + GetMergeResultErrorDetail (result); - monitor.ReportError (txt, null); - } - else if (result.GetMergeStatus () == MergeStatus.NOT_SUPPORTED) { - string msg = GettextCatalog.GetString ("Operation not supported"); - monitor.ReportError (msg, null); - DispatchService.GuiDispatch (delegate { - IdeApp.Workbench.StatusBar.ShowWarning (msg); - }); - } - else if (result.GetMergeStatus () == MergeStatus.CONFLICTING) { + if (status == StashApplyStatus.Conflicts) { string msg = GettextCatalog.GetString ("Stash applied with conflicts"); DispatchService.GuiDispatch (delegate { IdeApp.Workbench.StatusBar.ShowWarning (msg); @@ -189,23 +174,5 @@ namespace MonoDevelop.VersionControl.Git }); } } - - internal static string GetMergeResultErrorDetail (MergeCommandResult result) - { - string msg = ""; - if (result.GetFailingPaths () != null) { - foreach (var f in result.GetFailingPaths ()) { - if (msg.Length > 0) - msg += "\n"; - switch (f.Value) { - case NGit.Merge.ResolveMerger.MergeFailureReason.DIRTY_WORKTREE: msg += GettextCatalog.GetString ("The file '{0}' has unstaged changes", f.Key); break; - case NGit.Merge.ResolveMerger.MergeFailureReason.DIRTY_INDEX: msg += GettextCatalog.GetString ("The file '{0}' has staged changes", f.Key); break; - case NGit.Merge.ResolveMerger.MergeFailureReason.COULD_NOT_DELETE: msg += GettextCatalog.GetString ("The file '{0}' could not be deleted", f.Key); break; - } - } - } - return msg; - } } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitUtil.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitUtil.cs index 5ec0df4cbf..ff2b4fcc9f 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitUtil.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitUtil.cs @@ -1,21 +1,21 @@ -// +// // GitCommands.cs -// +// // Author: // Lluis Sanchez Gual <lluis@novell.com> -// +// // Copyright (c) 2010 Novell, Inc (http://www.novell.com) -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -24,347 +24,53 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. using System.IO; -using NGit; using System.Collections.Generic; using MonoDevelop.Core; -using NGit.Errors; -using NGit.Api.Errors; -using NGit.Dircache; -using NGit.Revwalk; -using NGit.Treewalk; -using NGit.Api; -using NGit.Merge; -using NGit.Transport; -using NGit.Diff; -using NGit.Internal; using System; using ProgressMonitor = MonoDevelop.Core.ProgressMonitor; +using LibGit2Sharp; namespace MonoDevelop.VersionControl.Git { - internal static class GitUtil + static class GitUtil { - public static string ToGitPath (this NGit.Repository repo, FilePath filePath) + public static string ToGitPath (this LibGit2Sharp.Repository repo, FilePath filePath) { - return filePath.FullPath.ToRelative (repo.WorkTree.ToString ()).ToString ().Replace ('\\', '/'); + return filePath.FullPath.ToRelative (repo.Info.WorkingDirectory).ToString ().Replace ('\\', '/'); } - public static IEnumerable<string> ToGitPath (this NGit.Repository repo, IEnumerable<FilePath> filePaths) + public static IEnumerable<string> ToGitPath (this LibGit2Sharp.Repository repo, IEnumerable<FilePath> filePaths) { foreach (var p in filePaths) yield return ToGitPath (repo, p); } - public static FilePath FromGitPath (this NGit.Repository repo, string filePath) + public static FilePath FromGitPath (this LibGit2Sharp.Repository repo, string filePath) { filePath = filePath.Replace ('/', Path.DirectorySeparatorChar); - return Path.Combine (repo.WorkTree, filePath); + return Path.Combine (repo.Info.WorkingDirectory, filePath); } - - public static List<string> GetConflictedFiles (NGit.Repository repo) - { - List<string> list = new List<string> (); - TreeWalk treeWalk = new TreeWalk (repo); - treeWalk.Reset (); - treeWalk.Recursive = true; - DirCache dc = repo.ReadDirCache (); - treeWalk.AddTree (new DirCacheIterator (dc)); - while (treeWalk.Next()) { - DirCacheIterator dirCacheIterator = treeWalk.GetTree<DirCacheIterator>(0); - var ce = dirCacheIterator.GetDirCacheEntry (); - if (ce != null && ce.Stage == 1) - list.Add (ce.PathString); - } - return list; - } - + /// <summary> /// Compares two commits and returns a list of files that have changed /// </summary> - public static IEnumerable<DiffEntry> CompareCommits (NGit.Repository repo, RevCommit reference, RevCommit compared) + public static TreeChanges CompareCommits (LibGit2Sharp.Repository repo, Commit reference, Commit compared) { - var changes = new List<DiffEntry>(); - if (reference == null && compared == null) - return changes; - ObjectId refTree = (reference != null ? reference.Tree.Id : ObjectId.ZeroId); - ObjectId comparedTree = (compared != null ? compared.Tree.Id : ObjectId.ZeroId); - return CompareCommits (repo, refTree, comparedTree); + return repo.Diff.Compare<TreeChanges> (reference != null ? reference.Tree : null, compared != null ? compared.Tree : null); } - - /// <summary> - /// Returns a list of files that have changed in a commit - /// </summary> - public static IEnumerable<DiffEntry> GetCommitChanges (NGit.Repository repo, RevCommit commit) - { - var rev = commit.ToObjectId (); - var prev = repo.Resolve (commit.Name + "^") ?? ObjectId.ZeroId; - return CompareCommits (repo, prev, rev); - } - - public static IEnumerable<DiffEntry> CompareCommits (NGit.Repository repo, AnyObjectId reference, ObjectId compared) - { - var diff = new MyersDiff (repo); - - if (reference != ObjectId.ZeroId) { - var firstTree = new CanonicalTreeParser (); - firstTree.Reset (repo.NewObjectReader (), new RevWalk (repo).ParseTree (reference)); - diff.SetOldTree (firstTree); - } - var secondTree = new CanonicalTreeParser (); - secondTree.Reset (repo.NewObjectReader (), new RevWalk (repo).ParseTree (compared)); - diff.SetNewTree (secondTree); - - return diff.Call (); - } - - public static ObjectId CreateCommit (NGit.Repository rep, string message, IList<ObjectId> parents, ObjectId indexTreeId, PersonIdent author, PersonIdent committer) - { - try { - ObjectInserter odi = rep.NewObjectInserter (); - try { - // Create a Commit object, populate it and write it - NGit.CommitBuilder commit = new NGit.CommitBuilder (); - commit.Committer = committer; - commit.Author = author; - commit.Message = message; - commit.SetParentIds (parents); - commit.TreeId = indexTreeId; - ObjectId commitId = odi.Insert (commit); - odi.Flush (); - return commitId; - } finally { - odi.Release (); - } - } catch (UnmergedPathException) { - // since UnmergedPathException is a subclass of IOException - // which should not be wrapped by a JGitInternalException we - // have to catch and re-throw it here - throw; - } catch (IOException e) { - throw new JGitInternalException ("Commit failed", e); - } - } - - public static void HardReset (NGit.Repository repo, string toRef) - { - ObjectId newHead = repo.Resolve (toRef); - HardReset (repo, newHead); - } - - public static void HardReset (NGit.Repository repo, ObjectId newHead) + public static TreeChanges GetChangedFiles (LibGit2Sharp.Repository repo, string refRev) { - DirCache dc = null; - - try { - // Reset head to upstream - RefUpdate ru = repo.UpdateRef (Constants.HEAD); - ru.SetNewObjectId (newHead); - ru.SetForceUpdate (true); - RefUpdate.Result rc = ru.Update (); - - switch (rc) { - case RefUpdate.Result.NO_CHANGE: - case RefUpdate.Result.NEW: - case RefUpdate.Result.FAST_FORWARD: - case RefUpdate.Result.FORCED: - break; - - case RefUpdate.Result.REJECTED: - case RefUpdate.Result.LOCK_FAILURE: - throw new ConcurrentRefUpdateException (JGitText.Get ().couldNotLockHEAD, ru.GetRef (), rc); - - default: - throw new JGitInternalException ("Reference update failed: " + rc); - } - - dc = repo.LockDirCache (); - RevWalk rw = new RevWalk (repo); - RevCommit c = rw.ParseCommit (newHead); - DirCacheCheckout checkout = new DirCacheCheckout (repo, null, dc, c.Tree); - checkout.Checkout (); - } catch { - if (dc != null) - dc.Unlock (); - throw; - } - } - - public static StashCollection GetStashes (NGit.Repository repo) - { - return new StashCollection (repo); - } - - public static IEnumerable<DiffEntry> GetChangedFiles (NGit.Repository repo, string refRev) - { - // Get a list of files that are different in the target branch - RevWalk rw = new RevWalk (repo); - ObjectId remCommitId = repo.Resolve (refRev); - if (remCommitId == null) - return null; - RevCommit remCommit = rw.ParseCommit (remCommitId); - - ObjectId headId = repo.Resolve (Constants.HEAD); - if (headId == null) - return null; - RevCommit headCommit = rw.ParseCommit (headId); - - return GitUtil.CompareCommits (repo, remCommit, headCommit); - } - - public static string GetUpstreamSource (NGit.Repository repo, string branch) - { - StoredConfig config = repo.GetConfig (); - string remote = config.GetString ("branch", branch, "remote"); - string rbranch = config.GetString ("branch", branch, "merge"); - if (string.IsNullOrEmpty (rbranch)) - return null; - if (rbranch.StartsWith (Constants.R_HEADS, System.StringComparison.Ordinal)) - rbranch = rbranch.Substring (Constants.R_HEADS.Length); - else if (rbranch.StartsWith (Constants.R_TAGS, System.StringComparison.Ordinal)) - rbranch = rbranch.Substring (Constants.R_TAGS.Length); - if (!string.IsNullOrEmpty (remote) && remote != ".") - return remote + "/" + rbranch; - else - return rbranch; - } - - public static void SetUpstreamSource (NGit.Repository repo, string branch, string remoteBranch) - { - StoredConfig config = repo.GetConfig (); - if (string.IsNullOrEmpty (remoteBranch)) { - config.UnsetSection ("branch", branch); - config.Save (); - return; - } - - int i = remoteBranch.IndexOf ('/'); - string upBranch; - if (i == -1) { - var tags = repo.GetTags (); - if (tags.ContainsKey (remoteBranch)) - upBranch = Constants.R_TAGS + remoteBranch; - else - upBranch = Constants.R_HEADS + remoteBranch; - config.SetString ("branch", branch, "remote", "."); - } else { - upBranch = Constants.R_HEADS + remoteBranch.Substring (i + 1); - config.SetString ("branch", branch, "remote", remoteBranch.Substring (0, i)); - } - config.SetString ("branch", branch, "merge", upBranch); - config.Save (); - } - - public static LocalGitRepository Init (string targetLocalPath, string url) - { - InitCommand ci = new InitCommand (); - ci.SetDirectory (targetLocalPath); - ci.Call (); - LocalGitRepository repo = new LocalGitRepository (Path.Combine (targetLocalPath, Constants.DOT_GIT)); - - string branch = Constants.R_HEADS + "master"; - - RefUpdate head = repo.UpdateRef (Constants.HEAD); - head.DisableRefLog (); - head.Link (branch); - - if (url != null) { - RemoteConfig remoteConfig = new RemoteConfig (repo.GetConfig (), "origin"); - remoteConfig.AddURI (new URIish (url)); - - string dst = Constants.R_REMOTES + remoteConfig.Name; - RefSpec wcrs = new RefSpec(); - wcrs = wcrs.SetForceUpdate (true); - wcrs = wcrs.SetSourceDestination (Constants.R_HEADS + "*", dst + "/*"); - - remoteConfig.AddFetchRefSpec (wcrs); - remoteConfig.Update (repo.GetConfig()); - } - - // we're setting up for a clone with a checkout - repo.GetConfig().SetBoolean ("core", null, "bare", false); - - repo.GetConfig().Save(); - return repo; + return GitUtil.CompareCommits (repo, repo.Lookup<Commit> (refRev), repo.Head.Tip); } - public static MergeCommandResult MergeTrees (NGit.ProgressMonitor monitor, NGit.Repository repo, RevCommit srcBase, RevCommit srcCommit, string sourceDisplayName, bool commitResult) + public static LibGit2Sharp.Repository Init (string targetLocalPath, string url) { - RevCommit newHead; - RevWalk revWalk = new RevWalk(repo); - try - { - // get the head commit - Ref headRef = repo.GetRef(Constants.HEAD); - if (headRef == null) - { - throw new NoHeadException(JGitText.Get().commitOnRepoWithoutHEADCurrentlyNotSupported - ); - } - RevCommit headCommit = revWalk.ParseCommit(headRef.GetObjectId()); - - ResolveMerger merger = (ResolveMerger)((ThreeWayMerger)MergeStrategy.RESOLVE.NewMerger - (repo)); - - merger.SetWorkingTreeIterator(new FileTreeIterator(repo)); - - merger.SetBase(srcBase); - - bool noProblems; - IDictionary<string, MergeResult<Sequence>> lowLevelResults = null; - IDictionary<string, ResolveMerger.MergeFailureReason> failingPaths = null; - IList<string> modifiedFiles = null; - - ResolveMerger resolveMerger = merger; - resolveMerger.SetCommitNames(new string[] { "BASE", "HEAD", sourceDisplayName }); - noProblems = merger.Merge(headCommit, srcCommit); - lowLevelResults = resolveMerger.GetMergeResults(); - modifiedFiles = resolveMerger.GetModifiedFiles(); - failingPaths = resolveMerger.GetFailingPaths(); - - if (monitor != null) - monitor.Update (50); - - if (noProblems) - { - if (modifiedFiles != null && modifiedFiles.Count == 0) { - return new MergeCommandResult(headCommit, null, new ObjectId[] { headCommit.Id, srcCommit - .Id }, MergeStatus.ALREADY_UP_TO_DATE, MergeStrategy.RESOLVE, null, null); - } - DirCacheCheckout dco = new DirCacheCheckout(repo, headCommit.Tree, repo.LockDirCache - (), merger.GetResultTreeId()); - dco.SetFailOnConflict(true); - dco.Checkout(); - if (commitResult) { - newHead = new NGit.Api.Git(repo).Commit().SetMessage(srcCommit.GetFullMessage() - ).SetAuthor(srcCommit.GetAuthorIdent()).Call(); - return new MergeCommandResult(newHead.Id, null, new ObjectId[] { headCommit.Id, srcCommit - .Id }, MergeStatus.MERGED, MergeStrategy.RESOLVE, null, null); - } else { - return new MergeCommandResult(headCommit, null, new ObjectId[] { headCommit.Id, srcCommit - .Id }, MergeStatus.MERGED, MergeStrategy.RESOLVE, null, null); - } - } - else - { - if (failingPaths != null) - { - return new MergeCommandResult(null, merger.GetBaseCommit(0, 1), new ObjectId[] { - headCommit.Id, srcCommit.Id }, MergeStatus.FAILED, MergeStrategy.RESOLVE, lowLevelResults - , failingPaths, null); - } - else - { - return new MergeCommandResult(null, merger.GetBaseCommit(0, 1), new ObjectId[] { - headCommit.Id, srcCommit.Id }, MergeStatus.CONFLICTING, MergeStrategy.RESOLVE, lowLevelResults - , null); - } - } - } - finally - { - revWalk.Release(); - } + var path = LibGit2Sharp.Repository.Init (targetLocalPath); + var repo = new LibGit2Sharp.Repository (path); + if (!string.IsNullOrEmpty (url)) + repo.Network.Remotes.Add ("origin", url); + return repo; } internal static bool IsGitRepository (this FilePath path) @@ -373,20 +79,5 @@ namespace MonoDevelop.VersionControl.Git var newPath = path.Combine (".git"); return Directory.Exists (newPath) && Directory.Exists (newPath.Combine ("objects")) && Directory.Exists (newPath.Combine ("refs")); } - - public static bool IsValidBranchName (string name) - { - // List from: https://github.com/git/git/blob/master/refs.c#L21 - if (name.StartsWith (".", StringComparison.Ordinal) || - name.EndsWith ("/", StringComparison.Ordinal) || - name.EndsWith (".lock", StringComparison.Ordinal)) - return false; - - if (name.Contains (" ") || name.Contains ("~") || name.Contains ("..") || name.Contains ("^") || - name.Contains (":") || name.Contains ("\\") || name.Contains ("?") || name.Contains ("[")) - return false; - return true; - } } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitVersionControl.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitVersionControl.cs index 4fa21d255e..89d279df66 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitVersionControl.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitVersionControl.cs @@ -1,21 +1,21 @@ -// +// // GitVersionControl.cs -// +// // Author: // Dale Ragan <dale.ragan@sinesignal.com> -// +// // Copyright (c) 2010 SineSignal, LLC -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -32,23 +32,17 @@ namespace MonoDevelop.VersionControl.Git abstract class GitVersionControl : VersionControlSystem { readonly Dictionary<FilePath,GitRepository> repositories = new Dictionary<FilePath,GitRepository> (); - - static GitVersionControl () - { - // Initialize the credentials provider, to be used in all git operations - NGit.Transport.CredentialsProvider.SetDefault (new GitCredentials ()); - } - + public override string Name { get { return "Git"; } } - + public override bool IsInstalled { get { return true; } } - + public override Repository GetRepositoryReference (FilePath path, string id) { GitRepository repo; @@ -56,12 +50,12 @@ namespace MonoDevelop.VersionControl.Git repositories [path.CanonicalPath] = repo = new GitRepository (this, path, null); return repo; } - + protected override Repository OnCreateRepositoryInstance () { return new GitRepository (); } - + public override IRepositoryEditor CreateRepositoryEditor (Repository repo) { return new UrlBasedRepositoryEditor ((GitRepository)repo); @@ -75,7 +69,7 @@ namespace MonoDevelop.VersionControl.Git return path; return OnGetRepositoryPath (path.ParentDirectory, id); } - + internal void UnregisterRepo (GitRepository repo) { if (!repo.RootPath.IsNullOrEmpty) @@ -83,4 +77,3 @@ namespace MonoDevelop.VersionControl.Git } } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/MergeDialog.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/MergeDialog.cs index 15b18b1f74..af942e07a4 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/MergeDialog.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/MergeDialog.cs @@ -1,21 +1,21 @@ -// +// // MergeDialog.cs -// +// // Author: // Lluis Sanchez Gual <lluis@novell.com> -// +// // Copyright (c) 2010 Novell, Inc (http://www.novell.com) -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -29,6 +29,7 @@ using Gtk; using MonoDevelop.Core; using MonoDevelop.Ide; using MonoDevelop.Components; +using LibGit2Sharp; namespace MonoDevelop.VersionControl.Git { @@ -38,44 +39,49 @@ namespace MonoDevelop.VersionControl.Git readonly GitRepository repo; string currentSel; string currentType; + string currentRemote; readonly bool rebasing; - + public MergeDialog (GitRepository repo, bool rebasing) { this.Build (); - + this.repo = repo; this.rebasing = rebasing; - + store = new TreeStore (typeof(string), typeof(Xwt.Drawing.Image), typeof (string), typeof(string)); tree.Model = store; - - CellRendererImage crp = new CellRendererImage (); - TreeViewColumn col = new TreeViewColumn (); + + var crp = new CellRendererImage (); + var col = new TreeViewColumn (); col.PackStart (crp, false); col.AddAttribute (crp, "image", 1); - CellRendererText crt = new CellRendererText (); + var crt = new CellRendererText (); col.PackStart (crt, true); col.AddAttribute (crt, "text", 2); tree.AppendColumn (col); - + tree.Selection.Changed += HandleTreeSelectionChanged; - + if (rebasing) { labelHeader.Text = GettextCatalog.GetString ("Select the branch to which to rebase:"); checkStage.Label = GettextCatalog.GetString ("Stash/unstash local changes before/after rebasing"); buttonOk.Label = GettextCatalog.GetString ("Rebase"); } - + checkStage.Active = true; - + Fill (); } - + public string SelectedBranch { get { return currentSel; } } - + + public string RemoteName { + get { return currentRemote; } + } + public bool StageChanges { get { return checkStage.Active; } } @@ -90,30 +96,37 @@ namespace MonoDevelop.VersionControl.Git if (tree.Selection.GetSelected (out it)) { currentSel = (string) store.GetValue (it, 0); currentType = (string) store.GetValue (it, 3); + if (IsRemote) { + TreeIter it2; + store.IterParent (out it2, it); + currentRemote = (string)store.GetValue (it2, 2); + } else { + currentRemote = null; + } } else currentSel = null; UpdateStatus (); } - + void Fill () { store.Clear (); - + foreach (Branch b in repo.GetBranches ()) store.AppendValues (b.Name, ImageService.GetIcon ("vc-branch", IconSize.Menu), b.Name, "branch"); - + foreach (string t in repo.GetTags ()) store.AppendValues (t, ImageService.GetIcon ("vc-tag", IconSize.Menu), t, "tag"); - - foreach (RemoteSource r in repo.GetRemotes ()) { + + foreach (Remote r in repo.GetRemotes ()) { TreeIter it = store.AppendValues (null, ImageService.GetIcon ("vc-repository", IconSize.Menu), r.Name, null); foreach (string b in repo.GetRemoteBranches (r.Name)) store.AppendValues (it, r.Name + "/" + b, ImageService.GetIcon ("vc-branch", IconSize.Menu), b, "remote"); } UpdateStatus (); } - + void UpdateStatus () { if (currentSel != null) { @@ -143,4 +156,3 @@ namespace MonoDevelop.VersionControl.Git } } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/MyersDiff.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/MyersDiff.cs deleted file mode 100644 index d1d7751d7f..0000000000 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/MyersDiff.cs +++ /dev/null @@ -1,268 +0,0 @@ -//
-// MyersDiff.cs
-//
-// Author:
-// Speedy <>
-//
-// Copyright (c) 2013 Speedy
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using NGit.Api;
-using System.Collections.Generic;
-using NGit.Diff;
-using NGit.Treewalk;
-using NGit.Treewalk.Filter;
-using Sharpen;
-using NGit.Util.IO;
-using NGit;
-using NGit.Api.Errors;
-using NGit.Internal;
-using NGit.Dircache;
-using System.IO;
-
-namespace MonoDevelop.VersionControl.Git
-{
- sealed class MyersDiff : GitCommand<IList<DiffEntry>>
- {
- AbstractTreeIterator oldTree;
-
- AbstractTreeIterator newTree;
-
- bool cached;
-
- TreeFilter pathFilter = TreeFilter.ALL;
-
- bool showNameAndStatusOnly;
-
- OutputStream @out;
-
- int contextLines = -1;
-
- string sourcePrefix;
-
- string destinationPrefix;
-
- NGit.ProgressMonitor monitor = NGit.NullProgressMonitor.INSTANCE;
-
- protected internal MyersDiff (NGit.Repository repo) : base (repo)
- {
- }
-
- /// <summary>
- /// Executes the
- /// <code>Diff</code>
- /// command with all the options and parameters
- /// collected by the setter methods (e.g.
- /// <see cref="SetCached(bool)">SetCached(bool)</see>
- /// of this
- /// class. Each instance of this class should only be used for one invocation
- /// of the command. Don't call this method twice on an instance.
- /// </summary>
- /// <returns>a DiffEntry for each path which is different</returns>
- /// <exception cref="NGit.Api.Errors.GitAPIException"></exception>
- public override IList<DiffEntry> Call()
- {
- DiffFormatter diffFmt;
- if (@out != null && !showNameAndStatusOnly)
- {
- diffFmt = new DiffFormatter(new BufferedOutputStream(@out));
- }
- else
- {
- diffFmt = new DiffFormatter(NullOutputStream.INSTANCE);
- }
-
- try {
- diffFmt.SetRepository(repo);
- } catch (ArgumentException) {
- // This means diff algorithm is not supported.
- } finally {
- diffFmt.SetDiffAlgorithm (DiffAlgorithm.GetAlgorithm (DiffAlgorithm.SupportedAlgorithm.MYERS));
- }
-
- diffFmt.SetProgressMonitor(monitor);
- try
- {
- if (cached)
- {
- if (oldTree == null)
- {
- ObjectId head = repo.Resolve(Constants.HEAD + "^{tree}");
- if (head == null)
- {
- throw new NoHeadException(JGitText.Get().cannotReadTree);
- }
- CanonicalTreeParser p = new CanonicalTreeParser();
- ObjectReader reader = repo.NewObjectReader();
- try
- {
- p.Reset(reader, head);
- }
- finally
- {
- reader.Release();
- }
- oldTree = p;
- }
- newTree = new DirCacheIterator(repo.ReadDirCache());
- }
- else
- {
- if (oldTree == null)
- {
- oldTree = new DirCacheIterator(repo.ReadDirCache());
- }
- if (newTree == null)
- {
- newTree = new FileTreeIterator(repo);
- }
- }
- diffFmt.SetPathFilter(pathFilter);
- IList<DiffEntry> result = diffFmt.Scan(oldTree, newTree);
- if (showNameAndStatusOnly)
- {
- return result;
- }
- else
- {
- if (contextLines >= 0)
- {
- diffFmt.SetContext(contextLines);
- }
- if (destinationPrefix != null)
- {
- diffFmt.SetNewPrefix(destinationPrefix);
- }
- if (sourcePrefix != null)
- {
- diffFmt.SetOldPrefix(sourcePrefix);
- }
- diffFmt.Format(result);
- diffFmt.Flush();
- return result;
- }
- }
- catch (IOException e)
- {
- throw new JGitInternalException(e.Message, e);
- }
- finally
- {
- diffFmt.Release();
- }
- }
-
- /// <param name="cached">whether to view the changes you staged for the next commit</param>
- /// <returns>this instance</returns>
- public MyersDiff SetCached(bool cached)
- {
- this.cached = cached;
- return this;
- }
-
- /// <param name="pathFilter">parameter, used to limit the diff to the named path</param>
- /// <returns>this instance</returns>
- public MyersDiff SetPathFilter(TreeFilter pathFilter)
- {
- this.pathFilter = pathFilter;
- return this;
- }
-
- /// <param name="oldTree">the previous state</param>
- /// <returns>this instance</returns>
- public MyersDiff SetOldTree(AbstractTreeIterator oldTree)
- {
- this.oldTree = oldTree;
- return this;
- }
-
- /// <param name="newTree">the updated state</param>
- /// <returns>this instance</returns>
- public MyersDiff SetNewTree(AbstractTreeIterator newTree)
- {
- this.newTree = newTree;
- return this;
- }
-
- /// <param name="showNameAndStatusOnly">whether to return only names and status of changed files
- /// </param>
- /// <returns>this instance</returns>
- public MyersDiff SetShowNameAndStatusOnly(bool showNameAndStatusOnly
- )
- {
- this.showNameAndStatusOnly = showNameAndStatusOnly;
- return this;
- }
-
- /// <param name="out">the stream to write line data</param>
- /// <returns>this instance</returns>
- public MyersDiff SetOutputStream(OutputStream @out)
- {
- this.@out = @out;
- return this;
- }
-
- /// <summary>Set number of context lines instead of the usual three.</summary>
- /// <remarks>Set number of context lines instead of the usual three.</remarks>
- /// <param name="contextLines">the number of context lines</param>
- /// <returns>this instance</returns>
- public MyersDiff SetContextLines(int contextLines)
- {
- this.contextLines = contextLines;
- return this;
- }
-
- /// <summary>Set the given source prefix instead of "a/".</summary>
- /// <remarks>Set the given source prefix instead of "a/".</remarks>
- /// <param name="sourcePrefix">the prefix</param>
- /// <returns>this instance</returns>
- public MyersDiff SetSourcePrefix(string sourcePrefix)
- {
- this.sourcePrefix = sourcePrefix;
- return this;
- }
-
- /// <summary>Set the given destination prefix instead of "b/".</summary>
- /// <remarks>Set the given destination prefix instead of "b/".</remarks>
- /// <param name="destinationPrefix">the prefix</param>
- /// <returns>this instance</returns>
- public MyersDiff SetDestinationPrefix(string destinationPrefix
- )
- {
- this.destinationPrefix = destinationPrefix;
- return this;
- }
-
- /// <summary>The progress monitor associated with the diff operation.</summary>
- /// <remarks>
- /// The progress monitor associated with the diff operation. By default, this
- /// is set to <code>NullProgressMonitor</code>
- /// </remarks>
- /// <seealso cref="NGit.NullProgressMonitor">NGit.NullProgressMonitor</seealso>
- /// <param name="monitor">a progress monitor</param>
- /// <returns>this instance</returns>
- public MyersDiff SetProgressMonitor(ProgressMonitor monitor)
- {
- this.monitor = monitor;
- return this;
- }
- }
-}
-
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/NewStashDialog.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/NewStashDialog.cs index d7f3d0b820..626555a628 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/NewStashDialog.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/NewStashDialog.cs @@ -1,21 +1,21 @@ -// +// // NewStashDialog.cs -// +// // Author: // Lluis Sanchez Gual <lluis@novell.com> -// +// // Copyright (c) 2011 Novell, Inc (http://www.novell.com) -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -31,11 +31,12 @@ namespace MonoDevelop.VersionControl.Git public NewStashDialog () { this.Build (); + + entryComment.Activated += (o, e) => Respond (Gtk.ResponseType.Ok); } - + public string Comment { get { return entryComment.Text; } } } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/PushDialog.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/PushDialog.cs index b6e49740ef..a80e7c55cb 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/PushDialog.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/PushDialog.cs @@ -1,21 +1,21 @@ -// +// // PushDialog.cs -// +// // Author: // Lluis Sanchez Gual <lluis@novell.com> -// +// // Copyright (c) 2010 Novell, Inc (http://www.novell.com) -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -32,31 +32,31 @@ namespace MonoDevelop.VersionControl.Git partial class PushDialog : Gtk.Dialog { readonly GitRepository repo; - + public PushDialog (GitRepository repo) { this.Build (); this.repo = repo; HasSeparator = false; - + changeList.DiffLoader = DiffLoader; - - List<string> list = new List<string> (repo.GetRemotes ().Select (r => r.Name)); + + var list = new List<string> (repo.GetRemotes ().Select (r => r.Name)); foreach (string s in list) remoteCombo.AppendText (s); remoteCombo.Active = list.IndexOf (repo.GetCurrentRemote ()); - + UpdateChangeSet (); } - + public string SelectedRemote { get { return remoteCombo.ActiveText; } } - + public string SelectedRemoteBranch { get { return branchCombo.ActiveText; } } - + void UpdateRemoteBranches () { ((Gtk.ListStore)branchCombo.Model).Clear (); @@ -70,7 +70,7 @@ namespace MonoDevelop.VersionControl.Git branchCombo.AppendText (s); branchCombo.Active = list.IndexOf (repo.GetCurrentBranch ()); } - + void UpdateChangeSet () { if (remoteCombo.Active == -1 || branchCombo.Active == -1) { @@ -80,21 +80,20 @@ namespace MonoDevelop.VersionControl.Git ChangeSet changeSet = repo.GetPushChangeSet (remoteCombo.ActiveText, branchCombo.ActiveText); changeList.Load (changeSet); } - + DiffInfo[] DiffLoader (FilePath path) { return repo.GetPushDiff (remoteCombo.ActiveText, branchCombo.ActiveText); } - + protected virtual void OnRemoteComboChanged (object sender, System.EventArgs e) { UpdateRemoteBranches (); } - + protected virtual void OnBranchComboChanged (object sender, System.EventArgs e) { UpdateChangeSet (); } } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/Stash.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/Stash.cs index be5d4fd6d1..f7491ed5e6 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/Stash.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/Stash.cs @@ -1,21 +1,21 @@ -// +// // Stash.cs -// +// // Author: // Lluis Sanchez Gual <lluis@novell.com> -// +// // Copyright (c) 2010 Novell, Inc (http://www.novell.com) -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -24,388 +24,22 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -using System; -using System.Linq; -using System.IO; -using System.Collections.Generic; -using System.Collections; -using System.Text; -using NGit; -using NGit.Treewalk; -using NGit.Dircache; -using NGit.Revwalk; -using NGit.Api; +using LibGit2Sharp; namespace MonoDevelop.VersionControl.Git { - public class Stash + public static class StashCollectionExtensions { - internal string CommitId { get; private set; } - internal string FullLine { get; private set; } - internal StashCollection StashCollection { get; set; } - - /// <summary> - /// Who created the stash - /// </summary> - public PersonIdent Author { get; private set; } - - /// <summary> - /// Timestamp of the stash creation - /// </summary> - public DateTimeOffset DateTime { get; private set; } - - /// <summary> - /// Stash comment - /// </summary> - public string Comment { get; private set; } - - private Stash () + internal static void Remove (this StashCollection sc, Stash stash) { - } - - internal Stash (string prevStashCommitId, string commitId, PersonIdent author, string comment) - { - this.PrevStashCommitId = prevStashCommitId; - this.CommitId = commitId; - this.Author = author; - this.DateTime = DateTimeOffset.Now; - - // Skip "WIP on master: " - int i = comment.IndexOf (':'); - this.Comment = comment.Substring (i + 2); - - // Create the text line to be written in the stash log - - int secs = (int) (this.DateTime - new DateTimeOffset (1970, 1, 1, 0, 0, 0, TimeSpan.Zero)).TotalSeconds; - - TimeSpan ofs = this.DateTime.Offset; - string tz = string.Format ("{0}{1:00}{2:00}", (ofs.Hours >= 0 ? '+':'-'), Math.Abs (ofs.Hours), Math.Abs (ofs.Minutes)); - - StringBuilder sb = new StringBuilder (); - sb.Append (prevStashCommitId ?? new string ('0', 40)).Append (' '); - sb.Append (commitId).Append (' '); - sb.Append (author.GetName ()).Append (" <").Append (author.GetEmailAddress ()).Append ("> "); - sb.Append (secs).Append (' ').Append (tz).Append ('\t'); - sb.Append (comment); - FullLine = sb.ToString (); - } - - string prevStashCommitId; - - internal string PrevStashCommitId { - get { return prevStashCommitId; } - set { - prevStashCommitId = value; - if (FullLine != null) { - if (prevStashCommitId != null) - FullLine = prevStashCommitId + FullLine.Substring (40); - else - FullLine = new string ('0', 40) + FullLine.Substring (40); + int i = 0; + foreach (var s in sc) { + if (s.Name == stash.Name) { + sc.Remove (i); + break; } + ++i; } } - - - internal static Stash Parse (string line) - { - // Parses a stash log line and creates a Stash object with the information - - Stash s = new Stash (); - s.PrevStashCommitId = line.Substring (0, 40); - if (s.PrevStashCommitId.All (c => c == '0')) // And id will all 0 means no parent (first stash of the stack) - s.PrevStashCommitId = null; - s.CommitId = line.Substring (41, 40); - - string aname = string.Empty; - string amail = string.Empty; - - int i = line.IndexOf ('<'); - if (i != -1) { - aname = line.Substring (82, i - 82 - 1); - i++; - int i2 = line.IndexOf ('>', i); - if (i2 != -1) - amail = line.Substring (i, i2 - i); - - i2 += 2; - i = line.IndexOf (' ', i2); - int secs = int.Parse (line.Substring (i2, i - i2)); - DateTime t = new DateTime (1970, 1, 1) + TimeSpan.FromSeconds (secs); - string st = t.ToString ("yyyy-MM-ddTHH:mm:ss") + line.Substring (i + 1, 3) + ":" + line.Substring (i + 4, 2); - s.DateTime = DateTimeOffset.Parse (st, System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat); - s.Comment = line.Substring (i + 7); - i = s.Comment.IndexOf (':'); - if (i != -1) - s.Comment = s.Comment.Substring (i + 2); - } - s.Author = new PersonIdent (aname, amail); - s.FullLine = line; - return s; - } - - public MergeCommandResult Apply (ProgressMonitor monitor) - { - return StashCollection.Apply (monitor, this); - } - } - - public class StashCollection: IEnumerable<Stash> - { - readonly NGit.Repository _repo; - - internal StashCollection (NGit.Repository repo) - { - this._repo = repo; - } - - FileInfo StashLogFile { - get { - string stashLog = Path.Combine (_repo.Directory, "logs"); - stashLog = Path.Combine (stashLog, "refs"); - return new FileInfo (Path.Combine (stashLog, "stash")); - } - } - - FileInfo StashRefFile { - get { - string file = Path.Combine (_repo.Directory, "refs"); - return new FileInfo (Path.Combine (file, "stash")); - } - } - - public Stash Create (ProgressMonitor monitor) - { - return Create (monitor, null); - } - - public Stash Create (ProgressMonitor monitor, string message) - { - if (monitor != null) { - monitor.Start (1); - monitor.BeginTask ("Stashing changes", 100); - } - - UserConfig config = _repo.GetConfig ().Get (UserConfig.KEY); - RevWalk rw = new RevWalk (_repo); - ObjectId headId = _repo.Resolve (Constants.HEAD); - var parent = rw.ParseCommit (headId); - - PersonIdent author = new PersonIdent(config.GetAuthorName () ?? "unknown", config.GetAuthorEmail () ?? "unknown@(none)."); - - if (string.IsNullOrEmpty (message)) { - // Use the commit summary as message - message = parent.Abbreviate (7) + " " + parent.GetShortMessage (); - int i = message.IndexOfAny (new char[] { '\r', '\n' }); - if (i != -1) - message = message.Substring (0, i); - } - - // Create the index tree commit - ObjectInserter inserter = _repo.NewObjectInserter (); - DirCache dc = _repo.ReadDirCache (); - - if (monitor != null) - monitor.Update (10); - - var tree_id = dc.WriteTree (inserter); - inserter.Release (); - - if (monitor != null) - monitor.Update (10); - - string commitMsg = "index on " + _repo.GetBranch () + ": " + message; - ObjectId indexCommit = GitUtil.CreateCommit (_repo, commitMsg + "\n", new ObjectId[] {headId}, tree_id, author, author); - - if (monitor != null) - monitor.Update (20); - - // Create the working dir commit - tree_id = WriteWorkingDirectoryTree (parent.Tree, dc); - commitMsg = "WIP on " + _repo.GetBranch () + ": " + message; - var wipCommit = GitUtil.CreateCommit(_repo, commitMsg + "\n", new ObjectId[] { headId, indexCommit }, tree_id, author, author); - - if (monitor != null) - monitor.Update (20); - - string prevCommit = null; - FileInfo sf = StashRefFile; - if (sf.Exists) - prevCommit = File.ReadAllText (sf.FullName).Trim (' ','\t','\r','\n'); - - Stash s = new Stash (prevCommit, wipCommit.Name, author, commitMsg); - - FileInfo stashLog = StashLogFile; - File.AppendAllText (stashLog.FullName, s.FullLine + "\n"); - File.WriteAllText (sf.FullName, s.CommitId + "\n"); - - if (monitor != null) - monitor.Update (5); - - // Wipe all local changes - GitUtil.HardReset (_repo, Constants.HEAD); - - monitor.EndTask (); - s.StashCollection = this; - return s; - } - - ObjectId WriteWorkingDirectoryTree (RevTree headTree, DirCache index) - { - DirCache dc = DirCache.NewInCore (); - DirCacheBuilder cb = dc.Builder (); - - ObjectInserter oi = _repo.NewObjectInserter (); - try { - TreeWalk tw = new TreeWalk (_repo); - tw.Reset (); - tw.AddTree (new FileTreeIterator (_repo)); - tw.AddTree (headTree); - tw.AddTree (new DirCacheIterator (index)); - - while (tw.Next ()) { - // Ignore untracked files - if (tw.IsSubtree) - tw.EnterSubtree (); - else if (tw.GetFileMode (0) != NGit.FileMode.MISSING && (tw.GetFileMode (1) != NGit.FileMode.MISSING || tw.GetFileMode (2) != NGit.FileMode.MISSING)) { - WorkingTreeIterator f = tw.GetTree<WorkingTreeIterator>(0); - DirCacheIterator dcIter = tw.GetTree<DirCacheIterator>(2); - DirCacheEntry currentEntry = dcIter.GetDirCacheEntry (); - DirCacheEntry ce = new DirCacheEntry (tw.PathString); - if (!f.IsModified (currentEntry, true)) { - ce.SetLength (currentEntry.Length); - ce.LastModified = currentEntry.LastModified; - ce.FileMode = currentEntry.FileMode; - ce.SetObjectId (currentEntry.GetObjectId ()); - } - else { - long sz = f.GetEntryLength(); - ce.SetLength (sz); - ce.LastModified = f.GetEntryLastModified(); - ce.FileMode = f.EntryFileMode; - var data = f.OpenEntryStream(); - try { - ce.SetObjectId (oi.Insert (Constants.OBJ_BLOB, sz, data)); - } finally { - data.Close (); - } - } - cb.Add (ce); - } - } - - cb.Finish (); - return dc.WriteTree (oi); - } finally { - oi.Release (); - } - } - - internal MergeCommandResult Apply (NGit.ProgressMonitor monitor, Stash stash) - { - monitor.Start (1); - monitor.BeginTask ("Applying stash", 100); - ObjectId cid = _repo.Resolve (stash.CommitId); - RevWalk rw = new RevWalk (_repo); - RevCommit wip = rw.ParseCommit (cid); - RevCommit oldHead = wip.Parents.First(); - rw.ParseHeaders (oldHead); - MergeCommandResult res = GitUtil.MergeTrees (monitor, _repo, oldHead, wip, "Stash", false); - monitor.EndTask (); - return res; - } - - public void Remove (Stash s) - { - List<Stash> stashes = ReadStashes (); - Remove (stashes, s); - } - - public MergeCommandResult Pop (ProgressMonitor monitor) - { - List<Stash> stashes = ReadStashes (); - Stash last = stashes.Last (); - MergeCommandResult res = last.Apply (monitor); - if (res.GetMergeStatus () != MergeStatus.FAILED && res.GetMergeStatus () != MergeStatus.NOT_SUPPORTED) - Remove (stashes, last); - return res; - } - - public void Clear () - { - if (StashRefFile.Exists) - StashRefFile.Delete (); - if (StashLogFile.Exists) - StashLogFile.Delete (); - } - - void Remove (List<Stash> stashes, Stash s) - { - int i = stashes.FindIndex (st => st.CommitId == s.CommitId); - if (i != -1) { - stashes.RemoveAt (i); - Stash next = stashes.FirstOrDefault (ns => ns.PrevStashCommitId == s.CommitId); - if (next != null) - next.PrevStashCommitId = s.PrevStashCommitId; - if (stashes.Count == 0) { - // No more stashes. The ref and log files can be deleted. - StashRefFile.Delete (); - StashLogFile.Delete (); - return; - } - WriteStashes (stashes); - if (i == stashes.Count) { - // We deleted the head. Write the new head. - File.WriteAllText (StashRefFile.FullName, stashes.Last ().CommitId + "\n"); - } - } - } - - public IEnumerator<Stash> GetEnumerator () - { - return ReadStashes ().GetEnumerator (); - } - - List<Stash> ReadStashes () - { - // Reads the registered stashes - // Results are returned from the bottom to the top of the stack - - List<Stash> result = new List<Stash> (); - FileInfo logFile = StashLogFile; - if (!logFile.Exists) - return result; - - Dictionary<string,Stash> stashes = new Dictionary<string, Stash> (); - Stash first = null; - foreach (string line in File.ReadAllLines (logFile.FullName)) { - Stash s = Stash.Parse (line); - s.StashCollection = this; - if (s.PrevStashCommitId == null) - first = s; - else - stashes.Add (s.PrevStashCommitId, s); - } - while (first != null) { - result.Add (first); - stashes.TryGetValue (first.CommitId, out first); - } - return result; - } - - void WriteStashes (List<Stash> list) - { - StringBuilder sb = new StringBuilder (); - foreach (var s in list) { - sb.Append (s.FullLine); - sb.Append ('\n'); - } - File.WriteAllText (StashLogFile.FullName, sb.ToString ()); - } - - IEnumerator IEnumerable.GetEnumerator () - { - return GetEnumerator (); - } } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/StashManagerDialog.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/StashManagerDialog.cs index 284522c521..45cc2243bf 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/StashManagerDialog.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/StashManagerDialog.cs @@ -1,21 +1,21 @@ -// +// // StashManagerDialog.cs -// +// // Author: // Lluis Sanchez Gual <lluis@novell.com> -// +// // Copyright (c) 2011 Novell, Inc (http://www.novell.com) -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -27,8 +27,7 @@ using Gtk; using MonoDevelop.Core; using MonoDevelop.Components; using MonoDevelop.Ide; -using NGit.Revwalk; -using NGit; +using LibGit2Sharp; namespace MonoDevelop.VersionControl.Git { @@ -37,17 +36,17 @@ namespace MonoDevelop.VersionControl.Git readonly GitRepository repository; readonly ListStore store; readonly StashCollection stashes; - + public StashManagerDialog (GitRepository repo) { this.Build (); repository = repo; stashes = repo.GetStashes (); - + store = new ListStore (typeof(Stash), typeof(string), typeof(string)); list.Model = store; - + list.AppendColumn (GettextCatalog.GetString ("Date/Time"), new CellRendererText (), "text", 1); list.AppendColumn (GettextCatalog.GetString ("Comment"), new CellRendererText (), "text", 2); Fill (); @@ -55,19 +54,19 @@ namespace MonoDevelop.VersionControl.Git if (store.GetIterFirst (out it)) list.Selection.SelectIter (it); UpdateButtons (); - + list.Selection.Changed += delegate { UpdateButtons (); }; } - + void Fill () { - TreeViewState tvs = new TreeViewState (list, 0); + var tvs = new TreeViewState (list, 0); tvs.Save (); store.Clear (); foreach (var s in stashes) { - string name = s.Comment; + string name = s.Name; string branch = GitRepository.GetStashBranchName (name); if (branch != null) { if (branch == "_tmp_") @@ -75,56 +74,62 @@ namespace MonoDevelop.VersionControl.Git else name = GettextCatalog.GetString ("Local changes of branch '{0}'", branch); } - store.AppendValues (s, s.DateTime.LocalDateTime.ToString (), name); + store.AppendValues (s, s.Index.Author.When.LocalDateTime.ToString (), name); } tvs.Load (); } - + void UpdateButtons () { - vboxButtons.Sensitive = GetSelected () != null; + vboxButtons.Sensitive = GetSelectedIndex () != -1; + } + + int GetSelectedIndex () + { + TreeIter it; + if (!list.Selection.GetSelected (out it)) + return -1; + + return list.Selection.GetSelectedRows () [0].Indices [0]; } - + Stash GetSelected () { TreeIter it; if (!list.Selection.GetSelected (out it)) return null; + return (Stash) store.GetValue (it, 0); } - async void ApplyStashAndRemove (Stash s) + async void ApplyStashAndRemove(int s) { using (IdeApp.Workspace.GetFileStatusTracker ()) { - await GitService.ApplyStash (s); - stashes.Remove (s); + if (await GitService.ApplyStash (repository, s)) + stashes.Remove (s); } } protected void OnButtonApplyClicked (object sender, System.EventArgs e) { - Stash s = GetSelected (); - if (s != null) { - GitService.ApplyStash (s); + int s = GetSelectedIndex (); + if (s != -1) { + GitService.ApplyStash (repository, s); Respond (ResponseType.Ok); } } - + protected void OnButtonBranchClicked (object sender, System.EventArgs e) { Stash s = GetSelected (); + int stashIndex = GetSelectedIndex (); if (s != null) { - var dlg = new EditBranchDialog (repository, null, true); + var dlg = new EditBranchDialog (repository); try { if (MessageService.RunCustomDialog (dlg) == (int) ResponseType.Ok) { - ObjectId commit = repository.RootRepository.Resolve (s.CommitId); - var rw = new RevWalk (repository.RootRepository); - RevCommit c = rw.ParseCommit (commit); - RevCommit old = c.GetParent (0); - rw.ParseHeaders (old); - repository.CreateBranchFromCommit (dlg.BranchName, old); + repository.CreateBranchFromCommit (dlg.BranchName, s.Base); GitService.SwitchToBranch (repository, dlg.BranchName); - ApplyStashAndRemove (s); + ApplyStashAndRemove (stashIndex); } } finally { dlg.Destroy (); @@ -132,7 +137,7 @@ namespace MonoDevelop.VersionControl.Git Respond (ResponseType.Ok); } } - + protected void OnButtonDeleteClicked (object sender, System.EventArgs e) { Stash s = GetSelected (); @@ -145,12 +150,11 @@ namespace MonoDevelop.VersionControl.Git protected void OnButtonApplyRemoveClicked (object sender, System.EventArgs e) { - Stash s = GetSelected (); - if (s != null) { + int s = GetSelectedIndex (); + if (s != -1) { ApplyStashAndRemove (s); Respond (ResponseType.Ok); } } } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/UserInfoConflictDialog.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/UserInfoConflictDialog.cs index 4033898a02..bfd7930f89 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/UserInfoConflictDialog.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/UserInfoConflictDialog.cs @@ -1,21 +1,21 @@ -// +// // UserInfoConflictDialog.cs -// +// // Author: // Lluis Sanchez Gual <lluis@novell.com> -// +// // Copyright (c) 2010 Novell, Inc (http://www.novell.com) -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -38,10 +38,9 @@ namespace MonoDevelop.VersionControl.Git labelMD.Markup = "<b>" + GLib.Markup.EscapeText (mdInfo) + "</b>"; labelGit.Markup = "<b>" + GLib.Markup.EscapeText (gitInfo) + "</b>"; } - + public bool UseMonoDevelopConfig { get { return radioMD.Active; } } } } - diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/build_libgit2.sh b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/build_libgit2.sh new file mode 100644 index 0000000000..8f57096214 --- /dev/null +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/build_libgit2.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +pushd ../../../../external/libgit2sharp/ +LIBGIT2SHA=`cat LibGit2Sharp/libgit2_hash.txt` +SHORTSHA=${LIBGIT2SHA:0:7} + +if [[ -d libgit2/build ]] +then + pushd libgit2/build + + if [[ -n $(ls libgit2-${SHORTSHA}.*) ]] + then + exit 0 + else + popd + rm -rf libgit2/build + fi +fi + +cp libgit2/CMakeLists.txt libgit2/.CMakeLists.txt.mdcopy +echo 'SET(CMAKE_SKIP_RPATH TRUE)' > libgit2/CMakeLists.txt +cat libgit2/.CMakeLists.txt.mdcopy >> libgit2/CMakeLists.txt + +mkdir libgit2/build +pushd libgit2/build + +cmake -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo \ + -DTHREADSAFE:BOOL=ON \ + -DBUILD_CLAR:BOOL=OFF \ + -DUSE_SSH=ON \ + -DLIBGIT2_FILENAME=git2-$SHORTSHA \ + -DCMAKE_OSX_ARCHITECTURES="i386;x86_64" \ + .. + +cmake --build . +popd + +mv libgit2/.CMakeLists.txt.mdcopy libgit2/CMakeLists.txt +popd diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/gtk-gui/MonoDevelop.VersionControl.Git.CredentialsDialog.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/gtk-gui/MonoDevelop.VersionControl.Git.CredentialsDialog.cs index 94bb0a130f..b250286a69 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/gtk-gui/MonoDevelop.VersionControl.Git.CredentialsDialog.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/gtk-gui/MonoDevelop.VersionControl.Git.CredentialsDialog.cs @@ -5,12 +5,13 @@ namespace MonoDevelop.VersionControl.Git internal partial class CredentialsDialog { private global::Gtk.VBox vbox; + private global::Gtk.Label labelTop; + private global::Gtk.Button buttonCancel; - private global::Gtk.Button buttonOk; - private global::Gtk.Button buttonNo; - private global::Gtk.Button buttonYes; + private global::Gtk.Button buttonOk; + protected virtual void Build () { global::Stetic.Gui.Initialize (this); @@ -71,40 +72,12 @@ namespace MonoDevelop.VersionControl.Git w6.Position = 1; w6.Expand = false; w6.Fill = false; - // Container child dialog1_ActionArea.Gtk.ButtonBox+ButtonBoxChild - this.buttonNo = new global::Gtk.Button (); - this.buttonNo.CanFocus = true; - this.buttonNo.Name = "buttonNo"; - this.buttonNo.UseStock = true; - this.buttonNo.UseUnderline = true; - this.buttonNo.Label = "gtk-no"; - w4.Add (this.buttonNo); - global::Gtk.ButtonBox.ButtonBoxChild w7 = ((global::Gtk.ButtonBox.ButtonBoxChild)(w4 [this.buttonNo])); - w7.Position = 2; - w7.Expand = false; - w7.Fill = false; - // Container child dialog1_ActionArea.Gtk.ButtonBox+ButtonBoxChild - this.buttonYes = new global::Gtk.Button (); - this.buttonYes.CanFocus = true; - this.buttonYes.Name = "buttonYes"; - this.buttonYes.UseStock = true; - this.buttonYes.UseUnderline = true; - this.buttonYes.Label = "gtk-yes"; - w4.Add (this.buttonYes); - global::Gtk.ButtonBox.ButtonBoxChild w8 = ((global::Gtk.ButtonBox.ButtonBoxChild)(w4 [this.buttonYes])); - w8.Position = 3; - w8.Expand = false; - w8.Fill = false; if ((this.Child != null)) { this.Child.ShowAll (); } this.DefaultWidth = 500; this.DefaultHeight = 132; - this.buttonNo.Hide (); - this.buttonYes.Hide (); this.Show (); - this.buttonNo.Clicked += new global::System.EventHandler (this.OnButtonNoClicked); - this.buttonYes.Clicked += new global::System.EventHandler (this.OnButtonYesClicked); } } } diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/gtk-gui/MonoDevelop.VersionControl.Git.EditRemoteDialog.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/gtk-gui/MonoDevelop.VersionControl.Git.EditRemoteDialog.cs index 8e6139155d..215f288a5e 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/gtk-gui/MonoDevelop.VersionControl.Git.EditRemoteDialog.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/gtk-gui/MonoDevelop.VersionControl.Git.EditRemoteDialog.cs @@ -165,7 +165,6 @@ namespace MonoDevelop.VersionControl.Git this.DefaultHeight = 206; this.Hide (); this.entryUrl.Changed += new global::System.EventHandler (this.OnEntryUrlChanged); - this.entryPushUrl.Changed += new global::System.EventHandler (this.OnEntryPushUrlChanged); this.entryName.Changed += new global::System.EventHandler (this.OnEntryNameChanged); } } diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/gtk-gui/MonoDevelop.VersionControl.Git.GitConfigurationDialog.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/gtk-gui/MonoDevelop.VersionControl.Git.GitConfigurationDialog.cs index bce5b64967..316a12aa6c 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/gtk-gui/MonoDevelop.VersionControl.Git.GitConfigurationDialog.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/gtk-gui/MonoDevelop.VersionControl.Git.GitConfigurationDialog.cs @@ -34,6 +34,7 @@ namespace MonoDevelop.VersionControl.Git private global::Gtk.Button buttonRemoveRemote; private global::Gtk.HSeparator hseparator2; private global::Gtk.Button buttonTrackRemote; + private global::Gtk.Button buttonFetch; private global::Gtk.Label label2; private global::Gtk.Button buttonOk; @@ -298,17 +299,28 @@ namespace MonoDevelop.VersionControl.Git w25.Position = 4; w25.Expand = false; w25.Fill = false; - this.hbox2.Add (this.vbox5); - global::Gtk.Box.BoxChild w26 = ((global::Gtk.Box.BoxChild)(this.hbox2 [this.vbox5])); - w26.Position = 1; + // Container child vbox5.Gtk.Box+BoxChild + this.buttonFetch = new global::Gtk.Button (); + this.buttonFetch.CanFocus = true; + this.buttonFetch.Name = "buttonFetch"; + this.buttonFetch.UseUnderline = true; + this.buttonFetch.Label = global::Mono.Unix.Catalog.GetString ("Fetch"); + this.vbox5.Add (this.buttonFetch); + global::Gtk.Box.BoxChild w26 = ((global::Gtk.Box.BoxChild)(this.vbox5 [this.buttonFetch])); + w26.Position = 5; w26.Expand = false; w26.Fill = false; + this.hbox2.Add (this.vbox5); + global::Gtk.Box.BoxChild w27 = ((global::Gtk.Box.BoxChild)(this.hbox2 [this.vbox5])); + w27.Position = 1; + w27.Expand = false; + w27.Fill = false; this.vbox4.Add (this.hbox2); - global::Gtk.Box.BoxChild w27 = ((global::Gtk.Box.BoxChild)(this.vbox4 [this.hbox2])); - w27.Position = 0; + global::Gtk.Box.BoxChild w28 = ((global::Gtk.Box.BoxChild)(this.vbox4 [this.hbox2])); + w28.Position = 0; this.notebook1.Add (this.vbox4); - global::Gtk.Notebook.NotebookChild w28 = ((global::Gtk.Notebook.NotebookChild)(this.notebook1 [this.vbox4])); - w28.Position = 2; + global::Gtk.Notebook.NotebookChild w29 = ((global::Gtk.Notebook.NotebookChild)(this.notebook1 [this.vbox4])); + w29.Position = 2; // Notebook tab this.label2 = new global::Gtk.Label (); this.label2.Name = "label2"; @@ -316,14 +328,14 @@ namespace MonoDevelop.VersionControl.Git this.notebook1.SetTabLabel (this.vbox4, this.label2); this.label2.ShowAll (); w1.Add (this.notebook1); - global::Gtk.Box.BoxChild w29 = ((global::Gtk.Box.BoxChild)(w1 [this.notebook1])); - w29.Position = 0; + global::Gtk.Box.BoxChild w30 = ((global::Gtk.Box.BoxChild)(w1 [this.notebook1])); + w30.Position = 0; // Internal child MonoDevelop.VersionControl.Git.GitConfigurationDialog.ActionArea - global::Gtk.HButtonBox w30 = this.ActionArea; - w30.Name = "dialog1_ActionArea"; - w30.Spacing = 10; - w30.BorderWidth = ((uint)(5)); - w30.LayoutStyle = ((global::Gtk.ButtonBoxStyle)(4)); + global::Gtk.HButtonBox w31 = this.ActionArea; + w31.Name = "dialog1_ActionArea"; + w31.Spacing = 10; + w31.BorderWidth = ((uint)(5)); + w31.LayoutStyle = ((global::Gtk.ButtonBoxStyle)(4)); // Container child dialog1_ActionArea.Gtk.ButtonBox+ButtonBoxChild this.buttonOk = new global::Gtk.Button (); this.buttonOk.CanDefault = true; @@ -333,9 +345,9 @@ namespace MonoDevelop.VersionControl.Git this.buttonOk.UseUnderline = true; this.buttonOk.Label = "gtk-close"; this.AddActionWidget (this.buttonOk, -7); - global::Gtk.ButtonBox.ButtonBoxChild w31 = ((global::Gtk.ButtonBox.ButtonBoxChild)(w30 [this.buttonOk])); - w31.Expand = false; - w31.Fill = false; + global::Gtk.ButtonBox.ButtonBoxChild w32 = ((global::Gtk.ButtonBox.ButtonBoxChild)(w31 [this.buttonOk])); + w32.Expand = false; + w32.Fill = false; if ((this.Child != null)) { this.Child.ShowAll (); } @@ -353,6 +365,7 @@ namespace MonoDevelop.VersionControl.Git this.buttonEditRemote.Clicked += new global::System.EventHandler (this.OnButtonEditRemoteClicked); this.buttonRemoveRemote.Clicked += new global::System.EventHandler (this.OnButtonRemoveRemoteClicked); this.buttonTrackRemote.Clicked += new global::System.EventHandler (this.OnButtonTrackRemoteClicked); + this.buttonFetch.Clicked += new global::System.EventHandler (this.OnButtonFetchClicked); } } } diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/gtk-gui/gui.stetic b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/gtk-gui/gui.stetic index 6a100b622c..80457d97aa 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/gtk-gui/gui.stetic +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/gtk-gui/gui.stetic @@ -625,8 +625,9 @@ <property name="MemberName" /> <property name="CanFocus">True</property> <property name="Type">TextOnly</property> - <property name="Label" translatable="yes">_Push All Tags</property> + <property name="Label" translatable="yes">_Push</property> <property name="UseUnderline">True</property> + <signal name="Clicked" handler="OnButtonPushTagClicked" /> </widget> <packing> <property name="Position">1</property> @@ -642,6 +643,7 @@ <property name="UseStock">True</property> <property name="Type">StockItem</property> <property name="StockId">gtk-delete</property> + <signal name="Clicked" handler="OnButtonRemoveTagClicked" /> <property name="label">gtk-delete</property> </widget> <packing> @@ -787,6 +789,22 @@ <property name="Fill">False</property> </packing> </child> + <child> + <widget class="Gtk.Button" id="buttonFetch"> + <property name="MemberName" /> + <property name="CanFocus">True</property> + <property name="Type">TextOnly</property> + <property name="Label" translatable="yes">Fetch</property> + <property name="UseUnderline">True</property> + <signal name="Clicked" handler="OnButtonFetchClicked" /> + </widget> + <packing> + <property name="Position">5</property> + <property name="AutoSize">True</property> + <property name="Expand">False</property> + <property name="Fill">False</property> + </packing> + </child> </widget> <packing> <property name="Position">1</property> @@ -947,7 +965,7 @@ <widget class="Gtk.CheckButton" id="checkTrack"> <property name="MemberName" /> <property name="CanFocus">True</property> - <property name="Label" translatable="yes">Track a branch or tag:</property> + <property name="Label" translatable="yes">Track a branch:</property> <property name="DrawIndicator">True</property> <property name="HasLabel">True</property> <property name="UseUnderline">True</property> @@ -1052,7 +1070,7 @@ <child> <widget class="Gtk.Table" id="table3"> <property name="MemberName" /> - <property name="NRows">3</property> + <property name="NRows">2</property> <property name="NColumns">2</property> <property name="RowSpacing">6</property> <property name="ColumnSpacing">6</property> @@ -1078,29 +1096,6 @@ </packing> </child> <child> - <widget class="Gtk.Entry" id="entryPushUrl"> - <property name="MemberName" /> - <property name="CanFocus">True</property> - <property name="IsEditable">True</property> - <property name="InvisibleChar">●</property> - <signal name="Changed" handler="OnEntryPushUrlChanged" /> - </widget> - <packing> - <property name="TopAttach">2</property> - <property name="BottomAttach">3</property> - <property name="LeftAttach">1</property> - <property name="RightAttach">2</property> - <property name="AutoSize">True</property> - <property name="YOptions">Fill</property> - <property name="XExpand">True</property> - <property name="XFill">True</property> - <property name="XShrink">False</property> - <property name="YExpand">False</property> - <property name="YFill">True</property> - <property name="YShrink">False</property> - </packing> - </child> - <child> <widget class="Gtk.Entry" id="entryUrl"> <property name="MemberName" /> <property name="CanFocus">True</property> @@ -1161,25 +1156,6 @@ <property name="YShrink">False</property> </packing> </child> - <child> - <widget class="Gtk.Label" id="label9"> - <property name="MemberName" /> - <property name="LabelProp" translatable="yes">Push Url:</property> - </widget> - <packing> - <property name="TopAttach">2</property> - <property name="BottomAttach">3</property> - <property name="AutoSize">True</property> - <property name="XOptions">Fill</property> - <property name="YOptions">Fill</property> - <property name="XExpand">False</property> - <property name="XFill">True</property> - <property name="XShrink">False</property> - <property name="YExpand">False</property> - <property name="YFill">True</property> - <property name="YShrink">False</property> - </packing> - </child> </widget> <packing> <property name="Position">0</property> @@ -1392,7 +1368,7 @@ <property name="GeneratePublic">False</property> <property name="Title" translatable="yes">Git Credentials</property> <property name="WindowPosition">CenterOnParent</property> - <property name="Buttons">4</property> + <property name="Buttons">2</property> <property name="HelpButton">False</property> <child internal-child="VBox"> <widget class="Gtk.VBox" id="dialog1_VBox"> @@ -1432,7 +1408,7 @@ <property name="MemberName" /> <property name="Spacing">10</property> <property name="BorderWidth">5</property> - <property name="Size">4</property> + <property name="Size">2</property> <property name="LayoutStyle">End</property> <child> <widget class="Gtk.Button" id="buttonCancel"> @@ -1467,42 +1443,6 @@ <property name="Fill">False</property> </packing> </child> - <child> - <widget class="Gtk.Button" id="buttonNo"> - <property name="MemberName" /> - <property name="Visible">False</property> - <property name="CanFocus">True</property> - <property name="UseStock">True</property> - <property name="Type">StockItem</property> - <property name="StockId">gtk-no</property> - <property name="ResponseId">-1</property> - <signal name="Clicked" handler="OnButtonNoClicked" /> - <property name="label">gtk-no</property> - </widget> - <packing> - <property name="Position">2</property> - <property name="Expand">False</property> - <property name="Fill">False</property> - </packing> - </child> - <child> - <widget class="Gtk.Button" id="buttonYes"> - <property name="MemberName" /> - <property name="Visible">False</property> - <property name="CanFocus">True</property> - <property name="UseStock">True</property> - <property name="Type">StockItem</property> - <property name="StockId">gtk-yes</property> - <property name="ResponseId">-1</property> - <signal name="Clicked" handler="OnButtonYesClicked" /> - <property name="label">gtk-yes</property> - </widget> - <packing> - <property name="Position">3</property> - <property name="Expand">False</property> - <property name="Fill">False</property> - </packing> - </child> </widget> </child> </widget> diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Tests/BaseSvnRepositoryTests.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Tests/BaseSvnRepositoryTests.cs index 3a13ada0ac..3242a79b6c 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Tests/BaseSvnRepositoryTests.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Tests/BaseSvnRepositoryTests.cs @@ -50,7 +50,7 @@ namespace MonoDevelop.VersionControl.Subversion.Tests svnAdmin = new Process ();
info = new ProcessStartInfo ();
info.FileName = "svnadmin";
- info.Arguments = "create " + RemotePath + Path.DirectorySeparatorChar + "repo";
+ info.Arguments = "create " + RemotePath.Combine ("repo"); info.WindowStyle = ProcessWindowStyle.Hidden;
svnAdmin.StartInfo = info;
svnAdmin.Start ();
@@ -65,14 +65,13 @@ namespace MonoDevelop.VersionControl.Subversion.Tests info.Arguments = "-dr " + RemotePath;
info.WindowStyle = ProcessWindowStyle.Hidden;
SvnServe.StartInfo = info;
- SvnServe.Start ();
-
- // Create user to auth.
- using (var perm = File. CreateText (RemotePath + Path.DirectorySeparatorChar + "repo" +
- Path.DirectorySeparatorChar + "conf" + Path.DirectorySeparatorChar + "svnserve.conf")) {
- perm.WriteLine ("[general]");
- perm.WriteLine ("anon-access = write");
- perm.WriteLine ("[sasl]");
+ SvnServe.Start (); + + // Create user to auth. + using (var perm = File. CreateText (RemotePath.Combine("repo", "conf", "svnserve.conf"))) { + perm.WriteLine ("[general]"); + perm.WriteLine ("anon-access = write"); + perm.WriteLine ("[sasl]"); }
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Tests/RepositoryTests.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Tests/RepositoryTests.cs index b55605ff85..ddbc5124ab 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Tests/RepositoryTests.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Tests/RepositoryTests.cs @@ -71,6 +71,7 @@ namespace VersionControl.Subversion.Unix.Tests +++ testfile (working copy) @@ -0,0 +1 @@ +text +\ No newline at end of file "; Assert.AreEqual (difftext, Repo.GenerateDiff (LocalPath + "testfile", Repo.GetVersionInfo (LocalPath + "testfile", VersionInfoQueryFlags.IgnoreCache)).Content); } diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion/SubversionRepository.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion/SubversionRepository.cs index f6c9ad6c65..d44fa21aa8 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion/SubversionRepository.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion/SubversionRepository.cs @@ -59,6 +59,10 @@ namespace MonoDevelop.VersionControl.Subversion get { return true; }
}
+ public override bool SupportsRevertToRevision {
+ get { return true; }
+ }
+
new SubversionVersionControl VersionControlSystem {
get { return (SubversionVersionControl)base.VersionControlSystem; }
}
@@ -327,8 +331,8 @@ namespace MonoDevelop.VersionControl.Subversion Svn.Move (localSrcPath, localDestPath, force, monitor);
} else {
base.OnMoveFile (localSrcPath, localDestPath, force, monitor);
- if (!destIsVersioned)
- Add (localDestPath, false, monitor);
+ Add (localDestPath, false, monitor);
+ DeleteFile (localSrcPath, force, monitor, keepLocal: false);
}
} else {
if (!destIsVersioned && IsVersioned (localSrcPath)) {
@@ -337,6 +341,7 @@ namespace MonoDevelop.VersionControl.Subversion } else
base.OnMoveFile (localSrcPath, localDestPath, force, monitor);
}
+ ClearCachedVersionInfo (localSrcPath, localDestPath);
}
protected override void OnMoveDirectory (FilePath localSrcPath, FilePath localDestPath, bool force, ProgressMonitor monitor)
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/LogWidget.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/LogWidget.cs index 5e19927073..50ce8d9ad3 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/LogWidget.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/LogWidget.cs @@ -256,7 +256,8 @@ namespace MonoDevelop.VersionControl.Views if (info.Repository.SupportsRevertRevision) toolbar.Add (revertButton); - toolbar.Add (revertToButton); + if (info.Repository.SupportsRevertToRevision) + toolbar.Add (revertToButton); toolbar.Add (refreshButton); Gtk.HBox a = new Gtk.HBox (); diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Repository.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Repository.cs index aa9fd5342b..e4294a090d 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Repository.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Repository.cs @@ -134,6 +134,10 @@ namespace MonoDevelop.VersionControl public virtual bool SupportsRevertRevision { get { return false; } } + + public virtual bool SupportsRevertToRevision { + get { return false; } + } internal protected virtual VersionControlOperation GetSupportedOperations (VersionInfo vinfo) { diff --git a/main/src/addins/VersionControl/Subversion.Win32.Tests/RepositoryTests.cs b/main/src/addins/VersionControl/Subversion.Win32.Tests/RepositoryTests.cs index 6c9a2cd5e3..3d93fc42cf 100644 --- a/main/src/addins/VersionControl/Subversion.Win32.Tests/RepositoryTests.cs +++ b/main/src/addins/VersionControl/Subversion.Win32.Tests/RepositoryTests.cs @@ -61,6 +61,7 @@ namespace MonoDevelop.VersionControl.Subversion.Tests +++ testfile (working copy)
@@ -0,0 +1 @@
+text
+\ No newline at end of file
";
Assert.AreEqual (difftext, Repo.GenerateDiff (LocalPath + "testfile", Repo.GetVersionInfo (LocalPath + "testfile", VersionInfoQueryFlags.IgnoreCache)).Content.Replace ("\n", "\r\n"));
}
@@ -119,6 +120,13 @@ namespace MonoDevelop.VersionControl.Subversion.Tests Assert.IsTrue (repo2.IsUrlValid ("file:///c:/dir/repo"));
}
+ [Test] + [Ignore ("Url gets broken. ")] + public override void CorrectTextAtRevision () + { + base.CorrectTextAtRevision (); + } + protected override Repository GetRepo (string path, string url)
{
return new SubversionRepository (new SvnSharpClient (), url, path);
diff --git a/main/src/addins/VersionControl/Subversion.Win32/SvnSharpClient.cs b/main/src/addins/VersionControl/Subversion.Win32/SvnSharpClient.cs index eb20653b49..1ba7eb0cea 100644 --- a/main/src/addins/VersionControl/Subversion.Win32/SvnSharpClient.cs +++ b/main/src/addins/VersionControl/Subversion.Win32/SvnSharpClient.cs @@ -211,6 +211,7 @@ namespace SubversionAddinWindows {
var args = new SvnAddArgs {
Depth = recurse ? SvnDepth.Infinity : SvnDepth.Empty,
+ Force = true,
};
BindMonitor (monitor);
lock (client)
diff --git a/main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/CommonFileDialogExtensions.cs b/main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/CommonFileDialogExtensions.cs index 5ecb14e85d..8f3ad07d78 100644 --- a/main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/CommonFileDialogExtensions.cs +++ b/main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/CommonFileDialogExtensions.cs @@ -54,6 +54,7 @@ namespace MonoDevelop.Platform var fileDialog = dialog as CommonOpenFileDialog;
if (fileDialog != null) {
fileDialog.Multiselect = data.SelectMultiple;
+ fileDialog.ShowHiddenItems = data.ShowHidden;
if (data.Action == FileChooserAction.SelectFolder) {
fileDialog.IsFolderPicker = true;
return;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/ChildrenOperation.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/ChildrenOperation.cs new file mode 100644 index 0000000000..44d10ad863 --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/ChildrenOperation.cs @@ -0,0 +1,50 @@ +// +// ChildrenOperation.cs +// +// Author: +// iain holmes <iain@xamarin.com> +// +// Copyright (c) 2015 Xamarin, Inc +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Collections.Generic; + +namespace MonoDevelop.Components.AutoTest.Operations +{ + public class ChildrenOperation : Operation + { + public override List<AppResult> Execute (List<AppResult> resultSet) + { + List<AppResult> newResultSet = new List<AppResult> (); + + foreach (var result in resultSet) { + List<AppResult> flattenedChildren = result.FlattenChildren (); + if (flattenedChildren != null) { + newResultSet.AddRange (flattenedChildren); + } + + AutoTestService.CurrentSession.SessionDebug.SendDebugMessage ("Got {0} results from Children", flattenedChildren.Count); + } + + return newResultSet; + } + } +} + diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/ModelOperation.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/ModelOperation.cs index 71a52dd4df..c9c17af5ba 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/ModelOperation.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/ModelOperation.cs @@ -31,7 +31,7 @@ namespace MonoDevelop.Components.AutoTest.Operations public class ModelOperation : Operation { string ColumnName; - public ModelOperation (string columnName) + public ModelOperation (string columnName = null) { ColumnName = columnName; } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkTreeModelResult.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkTreeModelResult.cs index 93011c7999..856265617b 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkTreeModelResult.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkTreeModelResult.cs @@ -31,22 +31,22 @@ namespace MonoDevelop.Components.AutoTest.Results { public class GtkTreeModelResult : AppResult { - TreeView TView; + Widget ParentWidget; TreeModel TModel; int Column; TreeIter? resultIter; string DesiredText; - public GtkTreeModelResult (TreeView treeView, TreeModel treeModel, int column) + public GtkTreeModelResult (Widget parent, TreeModel treeModel, int column) { - TView = treeView; + ParentWidget = parent; TModel = treeModel; Column = column; } - public GtkTreeModelResult (TreeView treeView, TreeModel treeModel, int column, TreeIter iter) + public GtkTreeModelResult (Widget parent, TreeModel treeModel, int column, TreeIter iter) { - TView = treeView; + ParentWidget = parent; TModel = treeModel; Column = column; resultIter = iter; @@ -119,7 +119,7 @@ namespace MonoDevelop.Components.AutoTest.Results TreeIter currentIter = (TreeIter) resultIter; while (TModel.IterNext (ref currentIter)) { - newList.Add (new GtkTreeModelResult (TView, TModel, Column, currentIter)); + newList.Add (new GtkTreeModelResult (ParentWidget, TModel, Column, currentIter)); } return newList; @@ -133,8 +133,13 @@ namespace MonoDevelop.Components.AutoTest.Results } return (bool) AutoTestService.CurrentSession.UnsafeSync (delegate { - TView.Selection.SelectIter ((TreeIter)resultIter); - + if (ParentWidget is TreeView) { + TreeView treeView = (TreeView) ParentWidget; + treeView.Selection.SelectIter ((TreeIter) resultIter); + } else if (ParentWidget is ComboBox) { + ComboBox comboBox = (ComboBox) ParentWidget; + comboBox.SetActiveIter ((TreeIter) resultIter); + } return true; }); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkWidgetResult.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkWidgetResult.cs index 7a2943a026..d00592788a 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkWidgetResult.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkWidgetResult.cs @@ -81,6 +81,18 @@ namespace MonoDevelop.Components.AutoTest.Results // FIXME: Are there other property names? return (AppResult) AutoTestService.CurrentSession.UnsafeSync (delegate { + // Check for the combobox first and try to use the active text. + // If the active text fails then + ComboBox cb = resultWidget as ComboBox; + if (cb != null) { + string activeText = cb.ActiveText; + if (activeText == null) { + return null; + } + + return CheckForText (activeText, text, exact) ? this : null; + } + // Look for a Text property on the widget. PropertyInfo pinfo = resultWidget.GetType ().GetProperty ("Text"); if (pinfo != null) { @@ -102,18 +114,32 @@ namespace MonoDevelop.Components.AutoTest.Results }); } - public override AppResult Model (string column) + TreeModel ModelFromWidget (Widget widget) { - TreeView tv = resultWidget as TreeView; - if (tv == null) { + TreeView tv = widget as TreeView; + if (tv != null) { + return (TreeModel)AutoTestService.CurrentSession.UnsafeSync (() => tv.Model); + } + + ComboBox cb = widget as ComboBox; + if (cb == null) { return null; } - TreeModel model = (TreeModel) AutoTestService.CurrentSession.UnsafeSync (() => tv.Model); + return (TreeModel)AutoTestService.CurrentSession.UnsafeSync (() => cb.Model); + } + + public override AppResult Model (string column) + { + TreeModel model = ModelFromWidget (resultWidget); if (model == null) { return null; } + if (column == null) { + return new GtkTreeModelResult (resultWidget, model, 0); + } + // Check if the class has the SemanticModelAttribute Type modelType = model.GetType (); SemanticModelAttribute attr = modelType.GetCustomAttribute<SemanticModelAttribute> (); @@ -135,7 +161,7 @@ namespace MonoDevelop.Components.AutoTest.Results } //AutoTestService.CurrentSession.SessionDebug.SendDebugMessage ("{0} has {1} at column {2}", resultWidget, column, columnNumber); - return new GtkTreeModelResult (tv, model, columnNumber); + return new GtkTreeModelResult (resultWidget, model, columnNumber); } object GetPropertyValue (string propertyName) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppQuery.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppQuery.cs index f2285a3271..f77b075903 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppQuery.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppQuery.cs @@ -172,7 +172,7 @@ namespace MonoDevelop.Components.AutoTest return this; } - public AppQuery Model (string column) + public AppQuery Model (string column = null) { operations.Add (new ModelOperation (column)); return this; @@ -214,6 +214,12 @@ namespace MonoDevelop.Components.AutoTest return this; } + public AppQuery Children () + { + operations.Add (new ChildrenOperation ()); + return this; + } + public override string ToString () { StringBuilder builder = new StringBuilder (); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppResult.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppResult.cs index 4976411cb7..5a2f5de7ad 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppResult.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppResult.cs @@ -51,6 +51,25 @@ namespace MonoDevelop.Components.AutoTest public abstract bool Click (); public abstract bool TypeKey (char key, string state); public abstract bool Toggle (bool active); + + void AddChildrenToList (List<AppResult> children, AppResult child) + { + AppResult node = child.FirstChild; + children.Add (child); + + while (node != null) { + AddChildrenToList (children, node); + node = node.NextSibling; + } + } + + public List<AppResult> FlattenChildren () + { + List<AppResult> children = new List<AppResult> (); + AddChildrenToList (children, FirstChild); + + return children; + } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/ISelectFileDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/ISelectFileDialog.cs index a0e59d40aa..85f8f60ada 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/ISelectFileDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/ISelectFileDialog.cs @@ -60,6 +60,7 @@ namespace MonoDevelop.Components.Extensions get { return FilterSet.DefaultFilter; } set { FilterSet.DefaultFilter = value; } } + public bool ShowHidden { get; set; } } /// <summary> @@ -163,6 +164,16 @@ namespace MonoDevelop.Components.Extensions get { return data.DefaultFilter; } set { data.DefaultFilter = value; } } + + /// <summary> + /// Gets or sets whether the file dialog will show hidden files and folders. + /// show hidden. + /// </summary> + /// <value><c>true</c> if hidden files are shown; otherwise, <c>false</c>.</value> + public bool ShowHidden { + get { return data.ShowHidden; } + set { data.ShowHidden = value; } + } #region File filter utilities diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AddFileDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AddFileDialog.cs index bea366a76b..7eb44e4bdf 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AddFileDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AddFileDialog.cs @@ -64,6 +64,8 @@ namespace MonoDevelop.Ide.Projects protected override bool RunDefault () { FileSelector fdiag = new FileSelector (data.Title); + + fdiag.ShowHidden = data.ShowHidden; //add a combo that can be used to override the default build action ComboBox combo = new ComboBox (data.BuildActions ?? new string[0]); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj index 1fca08e4ce..8d615cc4ba 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj @@ -3484,6 +3484,7 @@ <Compile Include="MonoDevelop.Ide.Editor.Extension\AbstractBraceMatcher.cs" /> <Compile Include="MonoDevelop.Ide.Editor.Extension\BraceMatcherTextEditorExtension.cs" /> <Compile Include="MonoDevelop.Ide.Editor.Extension\BraceMatchingResult.cs" /> + <Compile Include="MonoDevelop.Components.AutoTest.Operations\ChildrenOperation.cs" /> </ItemGroup> <ItemGroup> <None Include="Makefile.am" /> diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/MessageService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/MessageService.cs index b8d750f1f1..9fdfba7018 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/MessageService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/MessageService.cs @@ -368,12 +368,14 @@ namespace MonoDevelop.Ide dialog.Title = BrandingService.ApplicationName; #if MAC - // If there is a native NSWindow model window running, we need - // to show the new dialog over that window. - if (NSApplication.SharedApplication.ModalWindow != null) - dialog.Shown += HandleShown; - else - PlaceDialog (dialog, parent); + DispatchService.GuiSyncDispatch (() => { + // If there is a native NSWindow model window running, we need + // to show the new dialog over that window. + if (NSApplication.SharedApplication.ModalWindow != null) + dialog.Shown += HandleShown; + else + PlaceDialog (dialog, parent); + }); #endif return GtkWorkarounds.RunDialogWithNotification (dialog); } diff --git a/main/tests/Makefile.am b/main/tests/Makefile.am index 5c08034b18..ed2d5c9fb5 100644 --- a/main/tests/Makefile.am +++ b/main/tests/Makefile.am @@ -76,7 +76,12 @@ uitest: @if test -n "$(assembly)"; then \ for asm in $(UITEST_ASSEMBLIES); do \ if test `basename $$asm` = $(assembly); then \ - ($(RUN_TEST) -xml=TestResult_`basename $$asm`.xml -labels $$asm) || exit $?; \ + if test -n "$(categories)"; then \ + ($(RUN_TEST) -xml=TestResult_`basename $$asm`.xml -labels -include=$(categories) $$asm) || exit $?; \ + fi; \ + if ! test -n "$(categories)"; then \ + ($(RUN_TEST) -xml=TestResult_`basename $$asm`.xml -labels $$asm) || exit $?; \ + fi; \ fi; \ done; \ fi diff --git a/main/tests/UnitTests/UnitTests.csproj b/main/tests/UnitTests/UnitTests.csproj index 4bf7591bb5..fcf82937ff 100644 --- a/main/tests/UnitTests/UnitTests.csproj +++ b/main/tests/UnitTests/UnitTests.csproj @@ -132,21 +132,6 @@ <Name>MonoDevelop.VersionControl.Git</Name> <Private>False</Private> </ProjectReference> - <ProjectReference Include="..\..\external\ngit\NGit\NGit.csproj"> - <Project>{E3BFF8B4-189C-496A-A817-7E8B31E22B91}</Project> - <Name>NGit</Name> - <Private>False</Private> - </ProjectReference> - <ProjectReference Include="..\..\external\ngit\Sharpen\Sharpen.csproj"> - <Project>{72944A6C-45FF-4EF8-B349-8C9CABF519D4}</Project> - <Name>Sharpen</Name> - <Private>False</Private> - </ProjectReference> - <ProjectReference Include="..\..\external\ngit\NSch\NSch.csproj"> - <Project>{A19E6F3F-A25B-4B01-8922-CF0CC35C781D}</Project> - <Name>NSch</Name> - <Private>False</Private> - </ProjectReference> <ProjectReference Include="..\..\src\addins\MonoDevelop.SourceEditor2\MonoDevelop.SourceEditor.csproj"> <Project>{F8F92AA4-A376-4679-A9D4-60E7B7FBF477}</Project> <Name>MonoDevelop.SourceEditor</Name> @@ -177,11 +162,6 @@ <Name>MonoDevelop.Deployment.Linux</Name> <Private>False</Private> </ProjectReference> - <ProjectReference Include="..\..\external\ngit\Sharpen.Unix\Sharpen.Unix.csproj"> - <Project>{849AE05D-0058-4A8C-A0E8-77DC6BB12E52}</Project> - <Name>Sharpen.Unix</Name> - <Private>False</Private> - </ProjectReference> <ProjectReference Include="..\..\external\nrefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj"> <Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project> <Name>ICSharpCode.NRefactory</Name> diff --git a/main/tests/UserInterfaceTests/MonoDevelopTests/ASPNETTemplateTests.cs b/main/tests/UserInterfaceTests/MonoDevelopTests/ASPNETTemplateTests.cs index 6d8085c68d..9b84a6db7b 100644 --- a/main/tests/UserInterfaceTests/MonoDevelopTests/ASPNETTemplateTests.cs +++ b/main/tests/UserInterfaceTests/MonoDevelopTests/ASPNETTemplateTests.cs @@ -29,6 +29,8 @@ using NUnit.Framework; namespace UserInterfaceTests { + [TestFixture] + [Category("ASP")] public class ASPNetTemplatesTest : CreateBuildTemplatesTestBase { readonly string aspCategory = "ASP.NET"; diff --git a/main/tests/UserInterfaceTests/MonoDevelopTests/DotNetTemplatesTest.cs b/main/tests/UserInterfaceTests/MonoDevelopTests/DotNetTemplatesTest.cs index 459b2768a3..0fb7cbffc1 100644 --- a/main/tests/UserInterfaceTests/MonoDevelopTests/DotNetTemplatesTest.cs +++ b/main/tests/UserInterfaceTests/MonoDevelopTests/DotNetTemplatesTest.cs @@ -31,6 +31,8 @@ using NUnit.Framework; namespace UserInterfaceTests { + [TestFixture] + [Category("DotNet")] public class MonoDevelopTemplatesTest : CreateBuildTemplatesTestBase { public MonoDevelopTemplatesTest () : base (Util.TestRunId) {} diff --git a/main/tests/UserInterfaceTests/MonoDevelopTests/MiscTemplatesTest.cs b/main/tests/UserInterfaceTests/MonoDevelopTests/MiscTemplatesTest.cs index 7fdc71fb70..9e391cd7e0 100644 --- a/main/tests/UserInterfaceTests/MonoDevelopTests/MiscTemplatesTest.cs +++ b/main/tests/UserInterfaceTests/MonoDevelopTests/MiscTemplatesTest.cs @@ -28,6 +28,8 @@ using NUnit.Framework; namespace UserInterfaceTests { + [TestFixture] + [Category("Misc")] public class MiscTemplatesTest : CreateBuildTemplatesTestBase { readonly string miscCategory = "Miscellaneous"; |