csharp: Download SVN source
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
{
ManualResetEvent _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.ShowDialog() == 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
_finishedReadingTree = 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 (_filesToDownload)
{
_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(string 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 (_filesToDownload.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 List<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 == null)
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, false) == 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>(); XmlDocument 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(file);
} 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.ReadLine()) != 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.IndexOf("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;
} #region 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.Timeout = 50000;
WebResponse webResponse = null;
Stream responseStream = 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(buffer, 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"); //考虑乱码问题
string data = client.DownloadString(url); return data;
}
}
#endregion delegate void WriteToScreenDelegate(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;
}
}
}
csharp: Download SVN source的更多相关文章
- Download all Apple open source OS X files at once
While it is well known that Mac OS X contains open source code, how to access and download that sour ...
- Spring 4 MVC example with Maven - [Source Code Download]
In this tutorial, we show you a Spring 4 MVC example, using Maven build tool. Technologies used : Sp ...
- SVN服务之VisualSVN-Server和TortoiseSVN
SVN客户端程序:TortoiseSVN SVN服务器程序:VisualSVN-Server 目前有个项目,需要版本服务器,由于习惯了svn的使用,让这边搭建一台svn服务器,做了一下整理,只满足 ...
- Windows下使用VisualSVN Server搭建SVN服务器
使用 VisualSVN Server来实现主要的 SVN功能则要比使用原始的 SVN和 Apache相配合来实现源代码的 SVN管理简单的多,下面就看看详细的说明. VisualSVN Server ...
- How to build the Robotics Library from source code on Windows
The Robotics Library is an open source C++ library for robot kinematics, motion planning and control ...
- PhoneGap奇怪的现象:File FileTransfer download, 手机相册检测不到下载下来的图片(解决)
我有个从服务器下载相片的功能在使用 File FileTransfer download api时,碰到了很奇怪的现象:图片已经从服务器里下载了,手机文件夹里也可以看到下载过来的图片,但是我的手机相册 ...
- Installing Python 3.5.2 from source
Here are the procedures we are to follow, Download the source code of an official Python release. Co ...
- pentaho kettle svn
svn://source.pentaho.org/svnkettleroot/big data : svn://source.pentaho.org/svnkettleroot/archive/pen ...
- ionic cordova file download and load
1.先添加插件 cordova plugin add org.apache.cordova.file cordova plugin add org.apache.cordova.file-transf ...
随机推荐
- 【NLP】Python NLTK获取文本语料和词汇资源
Python NLTK 获取文本语料和词汇资源 作者:白宁超 2016年11月7日13:15:24 摘要:NLTK是由宾夕法尼亚大学计算机和信息科学使用python语言实现的一种自然语言工具包,其收集 ...
- python 入门笔记
1.pip包安装 pip install *** pip 中http和https代理设置(/etc/profile) 2.强制保存 :w !sudo tee % 3.cffi是python调用C的包 ...
- .NET中AOP方便之神SheepAspect
SheepAspect 简介以及代码示列: SheepAspect是一个AOP框架为.NET平台,深受AspectJ.它静织目标组件作为一个编译后的任务(编译时把AOP代码植入). 多有特性时,可根据 ...
- 后缀数组的倍增算法(Prefix Doubling)
后缀数组的倍增算法(Prefix Doubling) 文本内容除特殊注明外,均在知识共享署名-非商业性使用-相同方式共享 3.0协议下提供,附加条款亦可能应用. 最近在自学习BWT算法(Burrows ...
- python 3.5 成功安装 scrapy 的步骤
http://www.cnblogs.com/hhh5460/p/5814275.html
- WebLogic的安装和配置以及MyEclipse中配置WebLogic
WebLogic 中间件: 是基础软件的一大类,属于可复用软件的范畴,顾名思义,中间件属于操作系统软件与应用软件的中间,比如:JDK,框架,weblogic. weblogic与tomcat区别 : ...
- 【夯实PHP基础】PHP常用类和函数总结
本文地址 代码提纲: 1. 字符串处理类及函数 2. 数组处理类及函数 3 .web处理类及函数 将常用的PHP的类和函数总结到这里,主要是 自己用过的,比较有感觉. 1. [字符串处理] 1)[ut ...
- BridgePattern(桥接模式)
/** * 桥接模式 * @author TMAC-J * 应用于多维度方案 * 用组合的形式代替继承 * 符合单一职责原则 * 一个类只有一个引起他变化的原因 * 增加程序灵活性 */ public ...
- 流程表单中js如何清空SheetUser控件数据?
昨天有人问我js怎么清空.我试了试,发现简单的赋给他空值,并没有用.只能给他赋一个真实存在的值才有用.于是跟踪了一下他的删除按钮. 效果如下 使用场景:可以根据字段的不同类别变更人员. js代码如下, ...
- CentOS7 + mono +Jexus 环境的搭建
CentOS7的安装和配置 1,从http://www.centos.org/下载CentOS7的镜像,并在VMWare中创建该镜像的虚拟机,为方便操作,把虚拟机的网络连接设置为桥接模式:在安装过程中 ...