Csharp: Download SVN source, csharpsvn
Using System; using System. collections. generic; using System. componentModel; using System. data; using System. drawing; using System. text; using System. windows. forms; using System. net; using System. text. regularExpressions; using System. IO; using System. threading; using System. xml; namespace DownloadSVN {// <summary> // SVN 2016-05-13 // Geovin Du edit /// </summary> public partial class MainForm: Form {Manu AlResetEvent _ waitingForStop; ManualResetEvent _ finishedReadingTree; List <FileDownloadData> _ filesToDownload; Thread _ readingThread; String _ selectedSourceType; public MainForm () {InitializeComponent (); this. comboBoxSourceType. selectedIndex = 0;} private void buttonBrowseTargetFolder_Click (object sender, EventArgs e) {using (FolderBrowserDialog fbd = new FolderBrowserDialog () {if (fbd. showDia Log () = DialogResult. OK) this. textBoxTargetFolder. text = fbd. selectedPath ;}} private void buttonGo_Click (object sender, EventArgs e) {if (_ readingThread = null) {_ selectedSourceType = this. comboBoxSourceType. text; Thread t = new Thread (new ThreadStart (Run); t. start (); _ readingThread = t; SetButtonGoText ("Stop");} else {Stop () ;}} void Run () {// Start downloading threads _ finishedReading Tree = new ManualResetEvent (false); _ waitingForStop = new ManualResetEvent (false); _ filesToDownload = new List <FileDownloadData> (); list <Thread> downloadThreads = new List <Thread> (); for (int I = 0; I <5; I ++) {Thread t = new Thread (new ThreadStart (DownloadFilesThread); t. start (); downloadThreads. add (t);} try {if (this. textBoxTargetFolder. text! = "") & (This. textBoxSourceSvnUrl. Text! = "") {String url = this. textBoxSourceSvnUrl. text; if (_ selectedSourceType = "GIT") RunSvn (this. textBoxTargetFolder. text, this. textBoxSourceSvnUrl. text, RepositoryType. GIT); else // "SVN" RunSvn (this. textBoxTargetFolder. text, this. textBoxSourceSvnUrl. text, RepositoryType. SVN);} else WriteToScreen ("Parameters not set. ");} catch (Exception ex) {WriteToScreen (" Failed: "+ ex); lock (_ filesToDown Load) {_ filesToDownload. clear () ;}} finally {_ finishedReadingTree. set () ;}// Wait for downloading threads WriteToScreen ("Waiting for file downloading threads to finish"); for (int I = 0; I <downloadThreads. count; I ++) downloadThreads [I]. join (); WriteToScreen ("Done. "); MessageBox. show ("Done", "Done"); _ readingThread = null; SetButtonGoText ("Start");} delegate void SetButtonGoTextDelegate (stri Ng text ); /// <summary> ///// </summary> /// <param name = "text"> </param> void SetButtonGoText (string text) {if (InvokeRequired = true) {this. invoke (new SetButtonGoTextDelegate (SetButtonGoText), text); return;} buttonGo. text = text;} // <summary> ///// </summary> void DownloadFilesThread () {while (true) {FileDownloadData fileDownloadData = null; lock (_ filesToDownload) {if (_ filesToDow Nload. count> 0) {fileDownloadData = _ filesToDownload [0]; _ filesToDownload. removeAt (0) ;}} if (fileDownloadData = null) & (_ finishedReadingTree. waitOne (0, false) = true) return; if (fileDownloadData! = Null) {bool retry = true; while (retry = true) {if (_ waitingForStop. waitOne (0, false) = true) return; try {DownloadFile (fileDownloadData. url, fileDownloadData. fileName); retry = false;} catch (Exception ex) {WriteToScreen ("Failed to download:" + ex. message) ;}} else {Thread. sleep (100) ;}}/// <summary> /// </summary> public enum RepositoryType {SVN, GIT} // <summary> ////// </Summary> /// <param name = "baseFolder"> </param> /// <param name = "baseUrl"> </param> /// <param name = "repositoryType"> </param> void RunSvn (string baseFolder, string baseUrl, RepositoryType repositoryType) {if (repositoryType = RepositoryType. SVN) {if (baseUrl. endsWith ("/") = false) baseUrl + = "/";} if (baseFolder. endsWith ("\") = false) baseFolder + = "\"; List <FolderLinkData> urls = new Lis T <FolderLinkData> (); urls. add (new FolderLinkData (baseUrl, ""); while (urls. count> 0) {if (_ waitingForStop. waitOne (0, false) = true) {WriteToScreen ("Stopping... "); lock (_ filesToDownload) {_ filesToDownload. clear ();} break;} FolderLinkData targetUrlData = urls [0]; string targetUrl = targetUrlData. url; urls. removeAt (0); // Create the folder string relative; if (targetUrlData. relativePath = n Ull) relative = targetUrl. substring (baseUrl. length); else relative = targetUrlData. relativePath; relative = relative. replace ("/", "\"); string targetFolder = Path. combine (baseFolder, relative); if (Directory. exists (targetFolder) = false) Directory. createDirectory (targetFolder); // Download target page string page = null; bool retry = true; while (retry = true) {if (_ waitingForStop. waitOne (0, f Alse) = true) return; try {page = DownloadUrl (targetUrl); retry = false;} catch (Exception ex) {WriteToScreen ("Failed to download:" + ex. message) ;}} if (repositoryType = RepositoryType. SVN) {List <string> links = ParseLinks (page); foreach (string link in links) {string linkFullUrl = targetUrl + link; if (linkFullUrl. endsWith ("/") = true) {urls. add (new FolderLinkData (linkFullUrl, null ));} Else // file-download {string fileName = targetFolder + link; lock (_ filesToDownload) {_ filesToDownload. add (new FileDownloadData (linkFullUrl, fileName) ;}}} else if (repositoryType = RepositoryType. GIT) {List <PageLink> links = ParseGitLinks (page); int pos = targetUrl. indexOf ("/? "); String serverUrl = targetUrl. substring (0, pos); foreach (PageLink link in links) {string linkFullUrl = serverUrl + link. url; if (link. isFolder = true) urls. add (new FolderLinkData (linkFullUrl, targetUrlData. relativePath + link. name + "\"); else {string fileName = targetFolder + link. name; lock (_ filesToDownload) {_ filesToDownload. add (new FileDownloadData (linkFullUrl, fileName ));}}}}}} /// <Summary> //// </summary> /// <param name = "page"> </param> /// <returns> </ returns> List <string> ParseLinks (string page) {try {return ParseLinksFromXml (page);} catch {return ParseLinksFromHtml (page );}} /// <summary> ///// </summary> /// <param name = "page"> </param> /// <returns> </returns> List <string> ParseLinksFromXml (string page) {List <string> list = new List <string> (); XmlDocumen T doc = new XmlDocument (); doc. loadXml (page); XmlNode svnNode = doc. selectSingleNode ("/svn"); if (svnNode = null) throw new Exception ("Not a valid SVN xml"); foreach (XmlNode node in doc. selectNodes ("/svn/index/dir") {string dir = node. attributes ["href"]. value; list. add (dir);} foreach (XmlNode node in doc. selectNodes ("/svn/index/file") {string file = node. attributes ["href"]. value; list. add (f Ile);} return list ;} /// <summary> ///// </summary> /// <param name = "page"> </param> /// <returns> </returns> List <string> ParseLinksFromHtml (string page) {List <string> links = new List <string> (); string listArea = null; // Find list area: <ul>... </ul> int pos = page. indexOf ("<ul>"); if (pos> = 0) {int lastPos = page. indexOf ("</ul>", pos); if (lastPos> = 0) listArea = page. substring (pos + 4, LastPos-(pos + 4);} if (listArea! = Null) {string [] lines = listArea. split ('\ n'); string linePattern = "<a [^>] *> ([^ <] *) <"; for (int I = 0; I <lines. length; I ++) {Match match = Regex. match (lines [I], linePattern); if (match. success = true) {string linkRelUrl = match. groups [1]. value; if (linkRelUrl! = ".. ") Links. add (linkRelUrl) ;}} return links ;} /// <summary> ///// </summary> /// <param name = "page"> </param> /// <returns> </returns> List <PageLink> ParseGitLinks (string page) {List <PageLink> links = new List <PageLink> (); string dataStartMarker = "<td class = \" mode \ "> "; string nameMarker = "hb = HEAD \"> "; using (StringReader sr = new StringReader (page) {string line; while (line = sr. readLi Ne ())! = Null) {if (line. startsWith (dataStartMarker) = false) continue; bool isFolder = false; if (line [dataStartMarker. length] = 'D') isFolder = true; line = sr. readLine (); // Get name int pos = line. indexOf (nameMarker); int endPos = line. indexOf ("<", pos); pos + = nameMarker. length; string name = line. substring (pos, endPos-pos); if (name = ".. ") | (name = ". ") continue; // Get URL pos = line. in DexOf ("href = \" "); endPos = line. indexOf ("\"> ", pos); pos + =" href = \"". length; string url = line. substring (pos, endPos-pos); if (isFolder = false) {url = url. replace ("; a = blob;", "; a = blob_plain;"); pos = url. indexOf ("; h ="); url = url. substring (0, pos); url = url + "; hb = HEAD";} if (url. contains ("; a = tree;") isFolder = true; links. add (new PageLink (name, url, isFolder) ;}} return links ;}# regio N Download helper functions // <summary> /// </summary> /// <param name = "url"> </param> // <param name = "fileName"> </param> void DownloadFile (string url, string fileName) {WriteToScreen ("Downloading File:" + url); WebRequest webRequest = WebRequest. create (url); webRequest. contentType = "text/html; charset = UTF-8"; // webRequest with garbled characters. timeout = 50000; WebResponse webResponse = null; Stream res PonseStream = null; try {webResponse = webRequest. getResponse (); responseStream = webResponse. getResponseStream (); // string page = new StreamReader (responseStream, Encoding. UTF8, true ). readToEnd (); using (FileStream fs = new FileStream (fileName, FileMode. create) {byte [] buffer = new byte [1024]; int readSize; while (readSize = responseStream. read (buffer, 0, buffer. length)> 0) {fs. write (buff Er, 0, readSize) ;}} finally {if (responseStream! = Null) responseStream. Close (); if (webResponse! = Null) webResponse. close ();}} /// <summary> ///// </summary> /// <param name = "url"> </param> /// <returns> </returns> string DownloadUrl (string url) {WriteToScreen ("Downloading:" + url); using (WebClient client = new WebClient () {client. encoding = System. text. encoding. UTF8; // GetEncoding ("UTF-8"); // consider the garbled problem string data = client. downloadString (url); return data ;}# endregion delegate void Wr IteToScreenDelegate (string str ); /// <summary> ///// </summary> /// <param name = "str"> </param> void WriteToScreen (string str) {if (this. invokeRequired) {this. invoke (new WriteToScreenDelegate (WriteToScreen), str); return;} this. richTextBox1.AppendText (str + "\ n"); this. richTextBox1.ScrollToCaret ();} private void buttonClose_Click (object sender, EventArgs e) {this. close ();} private void Stop () {_ WaitingForStop. Set ();} private void MainForm_FormClosing (object sender, FormClosingEventArgs e) {if (_ readingThread! = Null) {Stop (); e. cancel = true ;}} public class PageLink {string _ name; string _ url; bool _ isFolder; public string Name {get {return _ name ;}} public string Url {get {return _ url;} public bool IsFolder {get {return _ isFolder;} public PageLink (string name, string url, bool isFolder) {_ name = name; _ url = url; _ isFolder = isFolder ;}} /// <summary> //// </summary> public class FolderLinkData {string _ url; string _ relativePath; public string Url {get {return _ url ;}} public string RelativePath {get {return _ relativePath;} public FolderLinkData (string url, string relativePath) {_ url = url; _ relativePath = relativePath ;}} /// <summary> //// </summary> public class FileDownloadData {string _ url; string _ fileName; public string Url {get {return _ url ;}} public string FileName {get {return _ fileName;} public FileDownloadData (string url, string fileName) {_ url = url; _ fileName = fileName ;}}}