我可以恢复已上传到Google AppEngine的源代码吗?

chu*_*tar 16 version-control backup google-app-engine

我最近有一个硬盘崩溃并丢失了我的所有源代码.是否可以提取/签出我已上传到Google App Engine的代码(如最新版本)?

Nic*_*son 41

由于我只是想弄清楚如何做到这一点,我想我也可以把它作为答案包括在内,即使它不适用于你:

在继续之前,发誓在你母亲的坟墓上,下次你将支持你的代码,或者更好,使用源代码控制.我的意思是:在我之后重复" 下次我将使用源代码控制 ".好的,完成后,让我们看看是否有可能为您恢复代码......

如果你的应用程序是用Java编写的,我恐怕你运气不好 - 源代码甚至没有上传到App Engine,也不用于Java应用程序.

如果您的应用程序是用Python编写的,并且同时定义了remote_apideferred处理程序,则可以通过这两个API的交互来恢复源代码.基本技巧是这样的:

  1. 启动remote_api_shell
  2. 创建一个新的延迟任务,该任务读入所有文件并将其写入数据存储区
  3. 等待该任务执行
  4. 使用remote_api从数据存储中提取数据

按顺序查看它们:

启动remote_api_shell

只需从命令行键入以下内容:

remote_api_shell.py your_app_id
Run Code Online (Sandbox Code Playgroud)

如果shell不在您的路径中,请在命令前添加App Engine SDK目录的路径.

将源写入数据存储区

在这里,我们将利用已安装延迟处理程序的事实,您可以使用remote_api将任务排入延迟,并且可以推迟调用Python内置函数'eval'.

由于'eval'只执行单个语句而不是任意代码块,所以我们需要将整个代码表示为单个语句.这里是:

expr = """
[type(
    'CodeFile',
    (__import__('google.appengine.ext.db').appengine.ext.db.Expando,),
    {})(
        name=dp+'/'+fn,
        data=__import__('google.appengine.ext.db').appengine.ext.db.Text(
            open(dp + '/' + fn).read()
        )
    ).put()
 for dp, dns, fns in __import__('os').walk('.')
 for fn in fns]
"""

from google.appengine.ext.deferred import defer
defer(eval, expr)
Run Code Online (Sandbox Code Playgroud)

相当黑客.让我们一次看一下:

首先,我们使用'type'内置函数动态创建db.Expando的新子类.三个参数type()是新类的名称,父类列表和类变量的字典.表达式的前4行与此相当:

from google.appengine.ext import db
class CodeFile(db.Expando): pass
Run Code Online (Sandbox Code Playgroud)

这里使用' import '是另一种解决方法,因为我们不能使用语句:表达式__import__('google.appengine.ext.db')导入引用的模块,并返回顶级模块(google).

由于type()返回了新类,我们现在有一个我们可以用来将数据存储到数据存储区的Expando子类.接下来,我们调用它的构造函数,传递两个参数,'name'和'data'.我们从目前正在处理的目录和文件的串联构造的名称,而数据是打开该文件名并读取其内容的结果,包装在db.Text对象中,因此它可以任意长.最后,我们在返回的实例上调用.put()将其存储到数据存储区.

为了读取和存储所有源代码而不是只有一个文件,整个表达式发生在列表解析中,它首先遍历os.walk的结果,它方便地返回基目录下的所有目录和文件,然后在每个目录中的每个文件上.此表达式的返回值 - 写入数据存储区的键列表 - 被延迟模块简单地丢弃.但这并不重要,因为它只是我们关心的副作用.

最后,我们调用defer函数,推迟调用eval,使用我们刚才描述的表达式作为参数.

读出数据

执行上述操作并等待其完成后,我们可以再次使用remote_api从数据存储中提取数据.首先,我们需要一个本地版本的代码文件模型:

import os
from google.appengine.ext import db
class CodeFile(db.Model):
  name = db.StringProperty(required=True)
  data = db.TextProperty(required=True)
Run Code Online (Sandbox Code Playgroud)

现在,我们可以获取它的所有实体,将它们存储到磁盘:

for cf in CodeFile.all():
  os.makedirs(os.dirname(cf.name))
  fh = open(cf.name, "w")
  fh.write(cf.data)
  fh.close()
Run Code Online (Sandbox Code Playgroud)

而已!您的本地文件系统现在应该包含您的源代码.

一个警告:下载的代码将只包含您的代码和数据文件.静态文件不包括在内,但是你应该能够通过HTTP简单地下载它们,如果你还记得它们的全部内容.配置文件,例如app.yaml,同样不包括在内,无法恢复 - 您需要重写它们.不过,比重写整个应用程序要好得多,对吧?


Ala*_*agu 32

更新: Google appengine现在允许您下载代码(适用于Python,Java,PHP和Go应用程序)

这里有工具文档.

  • 真的好消息.应该选择这个答案. (4认同)