SVN分支与合并

一些相关的概念和原理

分支(branch)和标记(tag)对于 SVN 来说就只是副本(copy),没有任何其它意义。分支和标记的意义是我们人为给予的。

· SVN 的副本是通过”cheap copies “来实现的,建立一个副本就类似 Unix 中创建一个硬链接(hard link),空间和时间的消耗都是固定并且很小的,因此不必太过担心副本太多而导致性能问题。

· SVN 的文件储存 是通过差异(diff)来实现的,底层储存方法有两种:1、Berkeley DB,完整保存一个文件的最新版本(revision),旧版本通过反向差异(reverse diffs)来获取。2、FSFS,跟 BDB 相反,完整保存一个文件的初始版本,后续版本通过正向差异来获取。当然,为了避免版本太多而造成性能下降,SVN 还使用了”skip-deltas “来减少需要追溯的版本数。

· SVN 属性(property )可以附带在文件、目录和版本(revision)上。文件和目录的属性类似文件内容,会被记录进版本库中的,例如每次提交时的注释,其实就是该版本的一个属性 svn:log。以”svn:”开头的属性是系统预留的,用户不应该自定义这样的属性。

进行分支开发的最佳实践

· 做分支上做开发的时候,必须定期使分支与主干同步,避免开发完成后合并(merge)回主干时出现严重冲突(confict)。

· 进行合并前,处理掉工作副本上的所有本地修改,方便合并失败时进行回滚(revert)。

· 进行合并时,特别注意 新增/删除 操作,因为很多冲突都是这类操作引起的。

· 完成一个分支的功能并合并回主干后,抛弃该分支,后续其它功能的开发使用新建的分支。当然,也有办法继续使用该分支。

合并的分类

1、从主干到分支(如果使用小乌龟选择第一项)

Svn代码

svn merge [-r M:N] ^/trunk

假设”^/trunk”是主干的 URL,当前目录为分支的工作副本。该命令同步主干的最新修改到当前工作副本,用于使分支跟主干保持同步。SVN 会通过 svn:mergeinfo 属性来记录当前工作副本已经合并过的版本号,然后在每次合并时选择合适的(eligible)版本进行合并。当然,也可以自己手动指定合并版本M到N的修改。

2、从分支到主干(如果使用小乌龟选择第二项)

Svn代码

svn merge –reintegrate ^/branches/quota

假设”^/branches/quota”是分支的 URL,当前目录为主干的工作副本。该命令将分支的最新版本(@HEAD)跟主干的最新版本进行比较,将差异实施到当前工作副本,用于将在分支上完成的工作合并回主干。

分支使用 –reintegrate 合并回主干后,如果继续在该分支上开发,当需要同步主干的修改到分支过来时,默认会包括之前 reintegrate 的修改,而这些修改已经在分支上做过了,所以这样往往会导致冲突。这也是前面“最佳实践”中最后一个建议的一个原因。当然,想要使这个分支继续可用也是可以的,这就需要使用下面这第三种合并。

这里要注意的是:假如分支的起始版本号是1000,现在主干上是2000,我们想合并主干的修改到分支,我们必须svn merge [-r 1000:2000] ^/trunk ,不能只合并比如1500到2000,否则在合并会主干时会有很大的问题。当出现这个问题时会提示分值上一些版本丢失,这个时候我们必须在这样在分值上做一边svn merge [-r 1000:2000] ^/trunk,然后在reintegration回trunk

3、仅记录的合并

Svn代码

svn merge -c 25 –record-only ^/trunk

假设当前目录为分支的工作副本,该命令将主干的版本25标记为已合并到当前工作副本,但并不会进行实质性的合并,这样下次合并主干到分支时,该版本的修改就会被跳过,避免修改被重复实施导致的冲突。其实这种合并就是改一下 svn:mergeinfo 而已,但直接修改太危险了,所以弄了这样一个所谓合并来规范操作。

from:http://www.cnblogs.com/cnblogsfans/archive/2011/02/16/1955808.html

分类: 版本管理 标签: svn, 版本管理

python开发环境配置三

2014年3月26日 dongdong 评论已被关闭

更新到Xcode5.1后,在虚拟环境下用pip安装出现各种问题,有Xcode5.1引起的,有其他原因引起的,现在记录下来以便日后不用再到处google。

1.Cannot fetch index base URL https://pypi.python.org/simple/

众所周知的原因,在安装的时候碰到这样的问题可以指定安装源-i http://pypi.douban.com/simpl,完整的命令为:

pip install Fabric -i http://pypi.douban.com/simple

这里用了豆瓣的源。

2.clang: error: unknown argument: ‘-mno-fused-madd’ [-Wunused-command-line-argument-hard-error-in-future]

安装Fabric的时候出现这样的错误,找了半天才在这里找到解决办法。要在安装命令前加上下面的命令:

ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future gem install GemName

完整的安装命令为:

ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future pip install Fabric -i http://pypi.douban.com/simple

3.EnvironmentError: mysql_config not found

指定mysql的配置文件

export PATH=$PATH:/usr/local/mysql/bin

然后再执行:

ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future pip install MySQL-python -i http://pypi.douban.com/simple

4.使用pod的时候发生下面的错误:


――― MARKDOWN TEMPLATE ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――

### Report

* What did you do?

* What did you expect to happen?

* What happened instead?

### Stack

```

CocoaPods : 0.28.0

Ruby : ruby 2.0.0p247 (2013-06-27 revision 41674) [universal.x86_64-darwin13]

RubyGems : 2.0.3

Host : Mac OS X 10.9.2 (13C64)

Xcode : 5.1 (5B130a)

Ruby lib dir : /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib

Repositories : master - https://github.com/CocoaPods/Specs.git @ 3d2a53e79f1e40499ece39a5dbcee2b54ef90aed

```

### Error

```

Psych::SyntaxError - (/Users/cenphoenix/.cocoapods/repos/master/CocoaPods-version.yml): mapping values are not allowed in this context at line 3 column 4

/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/psych.rb:205:in `parse'

/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/psych.rb:205:in `parse_stream'

/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/psych.rb:153:in `parse'

/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/psych.rb:129:in `load'

/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/psych.rb:299:in `block in load_file'

/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/psych.rb:299:in `open'

/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/psych.rb:299:in `load_file'

/Library/Ruby/Gems/2.0.0/gems/cocoapods-0.28.0/lib/cocoapods/sources_manager.rb:248:in `version_information'

/Library/Ruby/Gems/2.0.0/gems/cocoapods-0.28.0/lib/cocoapods/sources_manager.rb:209:in `repo_compatible?'

/Library/Ruby/Gems/2.0.0/gems/cocoapods-0.28.0/lib/cocoapods/sources_manager.rb:268:in `master_repo_functional?'

/Library/Ruby/Gems/2.0.0/gems/cocoapods-0.28.0/lib/cocoapods/command.rb:40:in `parse'

/Library/Ruby/Gems/2.0.0/gems/claide-0.4.0/lib/claide/command.rb:186:in `parse'

/Library/Ruby/Gems/2.0.0/gems/cocoapods-0.28.0/lib/cocoapods/command.rb:39:in `parse'

/Library/Ruby/Gems/2.0.0/gems/claide-0.4.0/lib/claide/command.rb:211:in `run'

/Library/Ruby/Gems/2.0.0/gems/cocoapods-0.28.0/lib/cocoapods/command.rb:52:in `run'

/Library/Ruby/Gems/2.0.0/gems/cocoapods-0.28.0/bin/pod:24:in `'

/usr/bin/pod:23:in `load'

/usr/bin/pod:23:in `
' ``` ――― TEMPLATE END ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― [!] Oh no, an error occurred. Search for existing github issues similar to yours: https://github.com/CocoaPods/CocoaPods/search?q=%28%2FUsers%2Fcenphoenix%2F.cocoapods%2Frepos%2Fmaster%2FCocoaPods-version.yml%29%3A+mapping+values+are+not+allowed+in+this+context+at+line+3+column+4&type=Issues If none exists, create a ticket, with the template displayed above, on: https://github.com/CocoaPods/CocoaPods/issues/new Don't forget to anonymize any private data!
 
    

解决办法:
1)删除cocoapods

sudo rm -fr ~/.cocoapods/repos/master

2)重新安装

pod setup

但是发生下面的错误:

Setting up CocoaPods master repo

[!] The `master` repo requires CocoaPods 0.29.0 -

Update CocoaPods, or checkout the appropriate tag in the repo.

3)运行下面命令:

sudo gem update cocoapods

4)最后运行:

pod setup

5.在django上添加上传文件的时候,发生下面的错误:

_("Neither Pillow nor PIL could be imported: %s") % err django.core.exceptions.ImproperlyConfigu

从错误看应该是未安装PIL或者Pillow,Image等包。
安装Pillow

pip install Pillow

发生下面错误

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include/tk.h:78:11: fatal error: 'X11/Xlib.h' file not found
#      include 
               ^
1 error generated.
error: command 'cc' failed with exit status 1
1
解决办法是:
1
ln -s  /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/Tk.framework/Versions/8.5/Headers/X11 /usr/local/include/X11
sudo pip install pil
分类: python 标签: Django, python, 问题

iOS开发工具——网络封包分析工具Charles

2013年12月30日 dongdong 评论已被关闭
From
http://www.infoq.com/cn/articles/network-packet-analysis-tool-charles
作者  唐巧 发布于 十二月 09, 2013

简介

Charles是在Mac下常用的截取网络封包的工具,在做iOS开发时,我们为了调试与服务器端的网络通讯协议,常常需要截取网络封包来分析。Charles通过将自己设置成系统的网络访问代理服务器,使得所有的网络访问请求都通过它来完成,从而实现了网络封包的截取和分析。

Charles是收费软件,可以免费试用30天。试用期过后,未付费的用户仍然可以继续使用,但是每次使用时间不能超过30分钟,并且启动时将会有10秒种的延时。

因此,该付费方案对广大用户还是相当友好的,即使你长期不付费,也能使用完整的软件功能。只是当你需要长时间进行封包调试时,会因为Charles强制关闭而遇到影响。

Charles主要的功能包括:

  1. 支持SSL代理。可以截取分析SSL的请求。
  2. 支持流量控制。可以模拟慢速网络以及等待时间(latency)较长的请求。
  3. 支持AJAX调试。可以自动将json或xml数据格式化,方便查看。
  4. 支持AMF调试。可以将Flash Remoting 或 Flex Remoting信息格式化,方便查看。
  5. 支持重发网络请求,方便后端调试。
  6. 支持修改网络请求参数。
  7. 支持网络请求的截获并动态修改。
  8. 检查HTML,CSS和RSS内容是否符合W3C标准。

安装Charles

去Charles的官方网站(http://www.charlesproxy.com)下载最新版的Charles安装包,是一个dmg后缀的文件。打开后将Charles拖到Application目录 下即完成安装。

安装SSL证书

如果你需要截取分析SSL协议相关的内容。那么需要安装Charles的CA证书。具体步骤如下:

  1. 去 http://www.charlesproxy.com/ssl.zip 下载CA证书文件。
  2. 解压该zip文件后,双击其中的.crt文件,这时候在弹出的菜单中选择“总是信任”,如下所示:
  3. 从钥匙串访问中即可看到添加成功的证书。如下所示:

将Charles设置成系统代理

之前提到,Charles是通过将自己设置成代理服务器来完成封包截取的,所以使用Charles的第一步是将其设置成系统的代理服务器。

启动Charles后,第一次Charles会请求你给它设置系统代理的权限。你可以输入登录密码授予Charles该权限。你也可以忽略该请求,然后在需要将Charles设置成系统代理时,选择菜单中的 “Proxy” -> “Mac OS X Proxy”来将Charles设置成系统代理。如下所示:

之后,你就可以看到源源不断的网络请求出现在Charles的界面中。

Charles主界面介绍

Charles主要提供2种查看封包的视图,分别名为“Structure”和”Sequence”。

  1. Structure视图将网络请求按访问的域名分类。
  2. Sequence视图将网络请求按访问的时间排序。

大家可以根据具体的需要在这两种视图之前来回切换。

对于某一个具体的网络请求,你可以查看其详细的请求内容和响应内容。如果响应内容是JSON格式的,那么Charles可以自动帮你将JSON内容格式化,方便你查看。

过滤网络请求

通常情况下,我们需要对网络请求进行过滤,只监控向指定目录服务器上发送的请求。对于这种需求,我们有2种办法。

  1. 在主界面的中部的Filter栏中填入需要过滤出来的关键字。例如我们的服务器的地址是:http://yuantiku.com,那么只需要在Filter栏中填入yuantiku即可。
  2. 在Charles的菜单栏选择”Proxy”->”Recording Settings”,然后选择Include栏,选择添加一个项目,然后填入需要监控的协议,主机地址,端口号。这样就可以只截取目标网站的封包了。如下图所示:

通常情况下,我们使用方法1做一些临时性的封包过滤,使用方法2做一些经常性的封包过滤。

截取iPhone上的网络封包

Charles通常用来截取本地上的网络封包,但是当我们需要时,我们也可以用来截取其它设备上的网络请求。下面我就以iPhone为例,讲解如何进行相应操作。

Charles上的设置

要截取iPhone上的网络请求,我们首先需要将Charles的代理功能打开。在Charles的菜单栏上选择“Proxy”->”Proxy Settings”,填入代理端口8888,并且勾上”Enable transparent HTTP proxying” 就完成了在Charles上的设置。如下图所示:

iPhone上的设置

首先我们需要获取Charles运行所在电脑的IP地址,打开Terminal,输入ifconfig en0, 即可获得该电脑的IP,如下图所示:

在iPhone的 “设置”->“无线局域网“中,可以看到当前连接的wifi名,通过点击右边的详情键,可以看到当前连接上的wifi的详细信息,包括IP地址,子网掩码等信息。在其最底部有“HTTP代理”一项,我们将其切换成手动,然后填上Charles运行所在的电脑的IP,以及端口号8888,如下图所示:

设置好之后,我们打开iPhone上的任意需要网络通讯的程序,就可以看到Charles弹出iPhone请求连接的确认菜单(如下图所示),点击“Allow”即可完成设置。

截取SSL信息

Charles默认并不截取SSL的信息,如果你想对截取某个网站上的所有SSL网络请求,可以在该请求上右击,选择SSL proxy,如下图所示:

这样,对于该Host的所有SSL请求可以被截取到了。

模拟慢速网络

在做iPhone开发的时候,我们常常需要模拟慢速网络或者高延迟的网络,以测试在移动网络下,应用的表现是否正常。Charles对此需求提供了很好的支持。

在Charles的菜单上,选择”Proxy”->”Throttle Setting”项,在之后弹出的对话框中,我们可以勾选上“Enable Throttling”,并且可以设置Throttle Preset的类型。如下图所示:

如果我们只想模拟指定网站的慢速网络,可以再勾选上图中的”Only for selected hosts”项,然后在对话框的下半部分设置中增加指定的hosts项即可。

修改网络请求内容

有些时候为了调试服务器的接口,我们需要反复尝试不同参数的网络请求。Charles可以方便地提供网络请求的修改和重发功能。只需要在以往的网络请求上点击右键,选择“Edit”,即可创建一个可编辑的网络请求。如下所示:

我们可以修改该请求的任何信息,包括url地址,端口,参数等,之后点击“Execute”即可发送该修改后的网络请求(如下图所示)。Charles支持我们多次修改和发送该请求,这对于我们和服务器端调试接口非常方便。

总结

通过Charles软件,我们可以很方便地在日常开发中,截取和调试网络请求内容,分析封包协议以及模拟慢速网络。用好Charles可以极大的方便我们对于带有网络请求的App的开发和调试。

参考链接:

  1. Charles主要的功能列表
  2. Charles官网

感谢李永伦对本文的审校。

分类: iphone技术 标签:

关于MacPorts、Fink、Homebrew

2013年9月25日 dongdong 评论已被关闭

Mac OS X是基于Unix的操作系统,可以安装大部分为Unix/Linux开发的软件。然而,如果只是以使用为目的,对每个软件都进行手工编译不是很方便,也不利于管理已安装的软件,于是出现了类似于Linux中APT、Yum(Ubuntu有apt-get, Red Hat和 CentOS有 yum)等类似的软件包管理系统,其中最著名的有MacPorts、Fink、Homebrew等。

我曾经是MacPorts的使用者,但了解Homebrew之后,立即“弃暗投明”了。其实MacPorts也是一个很不错的解决方案,除了一个实在让我头疼的特性。MacPorts有个原则,对于软件包之间的依赖,都在MacPorts内部解决(/opt/local),无论系统本身是否包含了需要的库,都不会加以利用。这使得MacPorts过分的庞大臃肿,导致系统出现大量软件包的冗余,占用不小的磁盘空间,同时稍大型一点的软件编译时间都会难以忍受。

而Homebrew的原则恰恰相反,它尽可能地利用系统自带的各种库,使得软件包的编译时间大为缩短;同时由于几乎不会造成冗余,软件包的管理也清晰、灵活了许多。Homebrew的另一个特点是使用Ruby定义软件包安装配置(叫做formula),定制非常简单。

至于Fink,由于并未安装使用过,不加讨论。(从互联网上的消息看,Fink由于维护人手的问题,软件包的更新不是很及时。)于我而言,Homebrew已经足够完善,除非发现重大的问题或者出现新的具有突破性的竞争对手,否则我没兴趣折腾别的软件包管理系统了。
下面说说Homebrew的安装与使用。
Homebrew的安装

注意: Homebrew 声明自己和 MacPorts 和 Fink 不兼容, 用它就不要用 MacPorts(或Fink)
首先确保你的系统满足如下要求:
基于Intel CPU
操作系统为Mac OS X 10.5 Leopard或更高版本
已安装版本管理工具Git(Mac OS X 10.7 Lion已经预安装)
已安装Xcode开发工具1
已安装Java Developer Update2
注1:Xcode 4.3中,命令行编译工具是可选安装,需要在Preferences > Downloads中激活。
注2:可选,Homebrew本身不依赖于Java,只有部分软件包的安装需要Java支持。
Homebrew的安装非常简单,在终端程序中输入以下命令即可(Homebrew 是用 Ruby 开发的, 这意味着, 你需要有一个 Ruby 解析器)。

ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)"

由于Homebrew的安装地址可能变化,请到官方网站 查看最新的安装方法。安装过程需要输入root口令。
Homebrew的使用
Homebrew的可执行命令是brew,其基本使用方法如下(以wget为例)。
查找软件包

brew search wget

安装软件包

brew install wget

列出已安装的软件包

brew list

删除软件包

brew remove wget

查看软件包信息

brew info wget

列出软件包的依赖关系

brew deps wget

更新brew

brew update

列出过时的软件包(已安装但不是最新版本)

brew outdated

更新过时的软件包(全部或指定)

brew upgrade 或 brew upgrade wget

定制自己的软件包

如果自己需要的软件包并不能在Homebrew中找到,怎么办呢,毕竟Homebrew是一个新生项目,不可能满足所有人的需求。当然,我们可以自行编译安装,但手工安装的软件包游离于Homebrew之外,管理起来不是很方便。

前文说过,Homebrew使用Ruby实现的软件包配置非常方便,下面简单谈一谈软件包的定制(假定软件包名称是bar,来自foo站点)。

首先找到待安装软件的源码下载地址

http://foo.com/bar-1.0.tgz

建立自己的formula
brew create http://foo.com/bar-1.0.tgz

编辑formula,上一步建立成功后,Homebrew会自动打开新建的formula进行编辑,也可用如下命令打开formula进行编辑。
brew edit bar
Homebrew自动建立的formula已经包含了基本的configure和make install命令,对于大部分软件,不需要进行修改,退出编辑即可。

输入以下命令安装自定义的软件包
brew install bar

卸载MacPorts

Hackintosh:~ liang$ sudo port -f uninstall installed
Hackintosh:~ liang$ sudo rm -rf \
/opt/local \
/Applications/DarwinPorts \
/Applications/MacPorts \
/Library/LaunchDaemons/org.macports.* \
/Library/Receipts/DarwinPorts*.pkg \
/Library/Receipts/MacPorts*.pkg \
/Library/StartupItems/DarwinPortsStartup \
/Library/Tcl/darwinports1.0 \
/Library/Tcl/macports1.0 \
~/.macports
分类: Mac 标签: Fink, Homebrew, MacPorts

关于easy_install,setuptools,pip,distribute等包管理工具

2013年9月25日 dongdong 评论已被关闭

Distribute 和 PIP都是python安装包的工具,python安装包的工具有easy_install, setuptools, pip,distribute。
使用这些工具都能下载并安装django等包。

Distribute是对标准库disutils模块的增强,我们知道disutils主要是用来更加容易的打包和分发包,特别是对其他的包有依赖的包。

安装Distribute
可以通过distribute_setup.py 脚本来安装Distribute,也可以通过easy_install, pip,源文件来安装,不过使用distribute_setup.py来安装是最简单和受欢迎的方式

Pip 是安装python包的工具,提供了安装包,列出已经安装的包,升级包以及卸载包的功能。
Pip 是对easy_install的取代,提供了和easy_install相同的查找包的功能,因此可以使用easy_install安装的包也同样可以使用pip进行安装。

安装Pip
Pip的安装可以通过源代码包,easy_install或者脚本。

easy_install:

$ easy_install pip
OK, 下面来看一下Pip的使用
安装package

$ pip install Markdown
列出安装的packages

$ pip freeze
安装特定版本的package
通过使用==, >=, <=, >, <来指定一个版本号。

$ pip install ‘Markdown<2.0′

$ pip install ‘Markdown>2.0,<2.0.3′
升级包
升级包到当前最新的版本,可以使用-U 或者 –upgrade

$ pip install -U Markdown
卸载包

$ pip uninstall Markdown
查询包

pip search “Markdown”

以下这两个图可以说明当前以及将来的发展趋向,distribute取代setuptools,pip取代easy_install

分类: python 标签: distribute, easy_install, pip, setuptools

使用south重命名model名称

2013年9月25日 dongdong 评论已被关闭

假设应用 foobar 有个 model:

class Foo(models.Model):
    foo = models.IntegerField()

想要将 model Foo 改名为 Bar

1.改好 models.py

class Bar(models.Model):
    foo = models.IntegerField()

2.执行 south 命令

# python manage.py schemamigration yourapp rename_model_foo_to_bar --auto
# 本例是
python manage.py schemamigration foobar rename_model_foo_to_bar --empty

3.更改生成的 000x_xxx.py 文件

class Migration(SchemaMigration):
    def forwards(self, orm):
        # 更改表名
        # db.rename_table('yourapp_foo', 'yourapp_bar')
        db.rename_table('foobar_foo', 'foobar_bar')

    def backwards(self, orm):
        # 撤销更改
        # db.rename_table('yourapp_bar', 'yourapp_foo')
        db.rename_table('foobar_bar', 'foobar_foo')
分类: python 标签:

python开发环境配置二:Django-south

2013年9月25日 dongdong 评论已被关闭

针对django自带的syncdb同步models和数据库的缺陷开发的数据迁移工具,可以作为syncdb的替代,South能够检测对models的更改并同步到数据库。

1.安装south
sudo pip install south
完成后在相应的django项目setting.py配置文件的INSTALLED_APPS中将south作为一个app导入

2.新建项目中使用south
在新项目中已经创建app对应的model,可以执行

python manage.py schemamigration you_app_name --initial
# --initial在数据库创建models定义的表,以及South需要的south_migrationhistory表,另外会在youappname目录下面创建一个migrations的子目录
#以后每次对models更改后,可以运行以下两条命令同步到数据库
python manage.py schemamigration you_app_name --auto #检测对models的更改
python manage.py migrate you_app_name #将更改反应到数据库
python manage.py migrate 00xx-migration-name #00xx-migration-name为你migrations目录下需要回滚的文件名

3.现有项目迁移到south
执行以下命令:
python manage.py syncdb #syncdb已经被South更改,用来创建south_migrationhistory表
在终端会看到提示:
(use ./manage.py migrate to migrate these)
按照提示执行:
python manage.py migrate
然后执行:
python manage.py convert_to_south you_app_name
此时我们可以在终端中看到在you_app_name目录下分别创建了migrations,__init__.py等south需要的目录和文件

总结如下:

1)创建一个没有数据库的新项目时
1、创建数据库
2、将south添加到INSTALLED_APPS
3、运行syncdb命令,它将django和south的数据表加入到数据库中
4、将你创建的apps添加到INSTALLED_APPS
5、对每个app分别运行“python manage.py schemamigration app_name –initial”,它将在每个app的目录下创建migration目录和相应的文件
6、然后运行“python manage.py migrate app_name”,这一步将app的数据表加入到数据库中
2)在带有数据库的已存项目中使用south
1、将south加入到INSTALLED_APPS中
2、运行syncdb,它将south的数据表加入到数据库中
3、对每个app分别运行python manage.py schemamigration app_name –initial,它将在每个app的目录下创建migration目录和相应的文件
4、对每个app分别运行“python manage.py migrate app_name 0001 –fake”,该命令不会对数据库做任何操作,只是欺骗一下south,让它在south_migrationhistory表中添加一些记录以便于下次你想创造migration文件的时候所有东西都已搞定。
3)在没有数据库的已存项目中使用south
1)创建数据库
2)将south加入到INSTALLED_APPS中
3)对每个app分别运行“python manage.py schemamigration app_name –initial”,它将在每个app的目录下创建migration目录和相应的文件
4)运行syncdb,它将所有没有migrations的apps加入到数据库中
5)然后运行“python manage.py migrate”命令,它将对你的所有apps运行迁移操作。

4.south原理

对应每次 models的更改执行schemamigration后会在migrations目录下面生成对应此次更改的py文件(South称之为 migrate),文件名形如0002_autodel_field_notes_create_user.py,同步数据库的时候会顺序(文件名 ASCII排序)执行这些py文件,文件里包含一个Migration的类,里面有两个方法forwards和backwards,将更改同步到数据库会 执行forwards方法,数据库操作失败会调用backwards实现rollback,South还提供了类似回溯的功能

常见问题
1. 添加和删除字段时可能会要求输入 default value(django里面models里面的许多字段默认都是null=False)
对于添加字段,输入的默认值必须和models定义的类型匹配,否则同步数据库的时候会报错
对于删除字段的情况,可以随意输入一个value而不管字段的默认类型,可以实现删除,但是并不可取,具体原因可以参见South的实现机制(rollback到删除字段之前会失败)。
2. 杀手锏
如果South在同步数据库的过程中出现错误,则migrations目录下面对应此次更改的python文件不会被执行,可以运行python manage.py migrate –list查看没有执行的py文件,文件名前面没有*表示该文件对应的更改没有反应到数据库,只需删除掉这些有问题的migrate,参照错误提示修改 models再同步即可,也可以直接更改对应的py文件修复错误

分类: python 标签:

python开发环境配置一:virtualenv创建虚拟python环境

2013年9月25日 dongdong 评论已被关闭

在不同项目的开发中,经常会碰到每个项目使用不同版本的第三方库,为防止将所有的安装包都安装到当前的site-packages(/Library/Python/2.7/site-packages/)下造成依赖或其他的影响,我们可以使用virtualenv和它的延展virtualenvwrapper来管理我们的Django安装。

1.安装virtualenv

sudo pip install virtualenv

2.安装virtualenvwrapper

sudo pip install virtualenvwrapper

3.配置虚拟环境

open ~/.bash_profile

在打开的文件中添加以下内容:

export WORKON_HOME=$HOME/.virtualenvs

export PROJECT_HOME=$HOME/directory-you-do-development-in

source /usr/local/bin/virtualenvwrapper.sh

保存后重启配置文件,使配置生效

source ~/.bash_profile

4.如何使用
创建一个虚拟环境:mkvirtualenv env1(该命令会在你上面配置WORKON_HOME的路径下创建env1目录)
退出环境:deactivate
进入已存在的环境或者切换环境:workon env1或者env2
删除环境:rmvirtualenv env1
当你进入到一个虚拟环境内,在你的shell前面会加上当前虚拟环境的名称的。
如我进入创建的虚拟环境test_project,在在终端的中会显示:(test_project)15MacBook-Pro:~
进入虚拟环境后,可以使用pip等命令安装需要的包,这些包只会在该虚拟环境中生效,和系统的和其他创建的虚拟环境都是相互独立的。
安装完django后,我们可以在终端中使用命令:
which django-admin.py
查看django-admin.py所在的路径,我们可以看到,django-admin.py在刚才我们创建的虚拟环境目录的bing目录下,完整的路径应该为:WORKON_HOME/env1/bin/django-admin.py

分类: python 标签:

TCP打洞技术

2012年6月26日 dongdong 评论已被关闭

from:http://hi.baidu.com/xiandanshiyi/item/80c3ac57de92f59c08be1755

建立穿越NAT设备的p2p的TCP连接只比UDP复杂一点点,TCP协议的“打洞”从协议层来看是与UDP
的“打洞”过程非常相似的。尽管如此,基于TCP协议的打洞至今为止还没有被很好的理解,这也
造成了对其提供支持的NAT设备不是很多。在NAT设备支持的前提下,基于TCP的“打洞”技术实际上
与基于UDP的“打洞”技术一样快捷、可靠。实际上,只要NAT设备支持的话,基于TCP的p2p技术
的健壮性将比基于UDP的技术的更强一些,因为TCP协议的状态机给出了一种标准的方法来精确的
获取某个TCP session的生命期,而UDP协议则无法做到这一点。

1 套接字和TCP端口的重用

实现基于TCP协议的p2p“打洞”过程中,最主要的问题不是来自于TCP协议,而是来自于来自于应用
程序的API接口。这是由于标准的伯克利(Berkeley)套接字的API是围绕着构建客户端/服务器程序
而设计的,API允许TCP流套接字通过调用connect()函数来建立向外的连接,或者通过listen()和
accept函数接受来自外部的连接,但是,API不提供类似UDP那样的,同一个端口既可以向外连接,
又能够接受来自外部的连接。而且更糟的是,TCP的套接字通常仅允许建立1对1的响应,即应用程
序在将一个套接字绑定到本地的一个端口以后,任何试图将第二个套接字绑定到该端口的操作都会
失败。

为了让TCP“打洞”能够顺利工作,我们需要使用一个本地的TCP端口来监听来自外部的TCP连接,同时
建立多个向外的TCP连接。幸运的是,所有的主流操作系统都能够支持特殊的TCP套接字参数,通常
叫做“SO_REUSEADDR”,该参数允许应用程序将多个套接字绑定到本地的一个endpoint(只要所有要
绑定的套接字都设置了SO_REUSEADDR参数即可)。BSD系统引入了SO_REUSEPORT参数,该参数用于区分
端口重用还是地址重用,在这样的系统里面,上述所有的参数必须都设置才行。

2 打开p2p的TCP流

假定客户端A希望建立与B的TCP连接。我们像通常一样假定A和B已经与公网上的已知服务器S建立了TCP
连接。服务器记录下来每个联入的客户端的公网和内网的endpoints,如同为UDP服务的时候一样。
从协议层来看,TCP“打洞”与UDP“打洞”是几乎完全相同的过程。

1)、客户端A使用其与服务器S的连接向服务器发送请求,要求服务器S协助其连接客户端B。
2)、S将B的公网和内网的TCP endpoint返回给A,同时,S将A的公网和内网的endpoint发送给B。
3)、客户端A和B使用连接S的端口异步地发起向对方的公网、内网endpoint的TCP连接,同时监听
各自的本地TCP端口是否有外部的连接联入。
4)、A和B开始等待向外的连接是否成功,检查是否有新连接联入。如果向外的连接由于某种网络
错误而失败,如:“连接被重置”或者“节点无法访问”,客户端只需要延迟一小段时间(例如
延迟一秒钟),然后重新发起连接即可,延迟的时间和重复连接的次数可以由应用程序编写者
来确定。
5)、TCP连接建立起来以后,客户端之间应该开始鉴权操作,确保目前联入的连接就是所希望的
连接。如果鉴权失败,客户端将关闭连接,并且继续等待新的连接联入。客户端通常采用
“先入为主”的策略,只接受第一个通过鉴权操作的客户端,然后将进入p2p通信过程不再继续
等待是否有新的连接联入。


(图 7)

与UDP不同的是,使用UDP协议的每个客户端只需要一个套接字即可完成与服务器S通信,
并同时与多个p2p客户端通信的任务,而TCP客户端必须处理多个套接字绑定到同一个本地
TCP端口的问题,如图7所示。

现在来看更加实际的一种情景,A与B分别位于不同的NAT设备后面,如图5所示,并且假定图中
的端口号是TCP协议的端口号,而不是UDP的端口号。图中向外的连接代表A和B向对方的内网
endpoint发起的连接,这些连接或许会失败或者无法连接到对方。如同使用UDP协议进行“打洞”
操作遇到的问题一样,TCP的“打洞”操作也会遇到内网的IP与“伪”公网IP重复造成连接失败或者
错误连接之类的问题。

客户端向彼此公网endpoint发起连接的操作,会使得各自的NAT设备打开新的“洞”允许A与B的
TCP数据通过。如果NAT设备支持TCP“打洞”操作的话,一个在客户端之间的基于TCP协议的流
通道就会自动建立起来。如果A向B发送的第一个SYN包发到了B的NAT设备,而B在此前没有向
A发送SYN包,B的NAT设备会丢弃这个包,这会引起A的“连接失败”或“无法连接”问题。而此时,
由于A已经向B发送过SYN包,B发往A的SYN包将被看作是由A发往B的包的回应的一部分,
所以B发往A的SYN包会顺利地通过A的NAT设备,到达A,从而建立起A与B的p2p连接。

3 从应用程序的角度来看TCP“打洞”

从应用程序的角度来看,在进行TCP“打洞”的时候都发生了什么呢?假定A首先向B发出SYN包,
该包发往B的公网endpoint,并且被B的NAT设备丢弃,但是B发往A的公网endpoint的SYN包则
通过A的NAT到达了A,然后,会发生以下的两种结果中的一种,具体是哪一种取决于操作系统
对TCP协议的实现:

(1)A的TCP实现会发现收到的SYN包就是其发起连接并希望联入的B的SYN包,通俗一点来说
就是“说曹操,曹操到”的意思,本来A要去找B,结果B自己找上门来了。A的TCP协议栈因此
会把B做为A向B发起连接connect的一部分,并认为连接已经成功。程序A调用的异步connect()
函数将成功返回,A的listen()等待从外部联入的函数将没有任何反映。此时,B联入A的操作
在A程序的内部被理解为A联入B连接成功,并且A开始使用这个连接与B开始p2p通信。

由于收到的SYN包中不包含A需要的ACK数据,因此,A的TCP将用SYN-ACK包回应B的公网endpoint,
并且将使用先前A发向B的SYN包一样的序列号。一旦B的TCP收到由A发来的SYN-ACK包,则把自己
的ACK包发给A,然后两端建立起TCP连接。简单的说,第一种,就是即使A发往B的SYN包被B的NAT
丢弃了,但是由于B发往A的包到达了A。结果是,A认为自己连接成功了,B也认为自己连接成功
了,不管是谁成功了,总之连接是已经建立起来了。

(2)另外一种结果是,A的TCP实现没有像(1)中所讲的那么“智能”,它没有发现现在联入的B
就是自己希望联入的。就好比在机场接人,明明遇到了自己想要接的人却不认识,误认为是其它
的人,安排别人给接走了,后来才知道是自己错过了机会,但是无论如何,人已经接到了任务
已经完成了。然后,A通过常规的listen()函数和accept()函数得到与B的连接,而由A发起的向
B的公网endpoint的连接会以失败告终。尽管A向B的连接失败,A仍然得到了B发起的向A的连接,
等效于A与B之间已经联通,不管中间过程如何,A与B已经连接起来了,结果是A和B的基于TCP协议
的p2p连接已经建立起来了。

第一种结果适用于基于BSD的操作系统对于TCP的实现,而第二种结果更加普遍一些,多数linux和
windows系统都会按照第二种结果来处理。

分类: 网络技术 标签:

UIWebView加载https的方法

2012年4月14日 dongdong 评论已被关闭

1

 NSURLRequest *request=[[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"https://two.e-jing.net/banny/data/aboutUs.html"]];
 NSURLConnection *urlConnection=[NSURLConnection connectionWithRequest:request delegate:self];
 [aboutWebView loadRequest:request];
 [self.loading startAnimating];

 

2.

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {

//  NSLog(@"We are checking protection Space!");

if([protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])

{

//NSLog(@"Can Auth Secure Requestes!");

return YES;

}

else if([protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic])

{

//NSLog(@"Can Auth Basic Requestes!");

return YES;

//return NO;

}

//NSLog(@"Cannot Auth!");

return NO;

}

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge {

if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])

{

[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];

[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];

}

else if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic])

{

NSURLCredential *credential = [[NSURLCredential alloc] initWithUser:@"banny" password:@"ejing2012" persistence:NSURLCredentialPersistenceForSession];

[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];

//  [credential release];

}

NSURLRequest *request=[[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"https://two.e-jing.net/banny/data/aboutUs.html"]];

[self.aboutWebView loadRequest:request];

}

 

但这样会加载2次

你可能感兴趣的:(中国iOS开发,SVN)