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

标签 google-app-engine version-control backup

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

最佳答案

由于我只是费了很大力气才弄清楚如何做到这一点,我想我也可以将其作为答案包含在内,即使它不适用于您:

在继续之前,在你母亲的坟墓上发誓下次你会备份你的代码,或者更好的是,使用源代码控制。我的意思是:在我之后重复“ 下次我将使用源代码管理”。好的,完成后,让我们看看是否可以为您恢复您的代码......

如果您的应用程序是用 Java 编写的,恐怕您就不走运了——Java 应用程序的源代码甚至没有上传到 App Engine。

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

  • 启动 remote_api_shell
  • 创建一个新的延迟任务,读取所有文件并将它们写入数据存储
  • 等待该任务执行
  • 使用 remote_api
  • 从数据存储中提取数据

    按顺序查看它们:

    启动 remote_api_shell

    只需从命令行键入以下内容:
    remote_api_shell.py your_app_id
    

    如果 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)
    

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

    首先,我们使用'type'内置函数动态创建db.Expando的新子类。 . type() 的三个参数是新类的名称、父类的列表和类变量的字典。整个表达式的前 4 行等价于:
    from google.appengine.ext import db
    class CodeFile(db.Expando): pass
    

    ' 的使用进口 ' 这是我们不能使用语句这一事实的另一种解决方法:表达式 __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)
    

    现在,我们可以获取它的所有实体,并将它们存储到磁盘:
    for cf in CodeFile.all():
      os.makedirs(os.dirname(cf.name))
      fh = open(cf.name, "w")
      fh.write(cf.data)
      fh.close()
    

    就是这样!您的本地文件系统现在应该包含您的源代码。

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

    关于google-app-engine - 我可以恢复已上传到 Google AppEngine 的源代码吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2479087/

    相关文章:

    python - Google App Engine 应用程序升级到 Python 3.x 的途径是什么?

    google-app-engine - 使用go在应用程序引擎中包含电子邮件 header ?

    svn - 解决svn中的属性冲突

    上传到 S3 时 Ruby Backup gem 失败。 37 分钟后连接重置

    linux - 从 Linux 备份到 Windows Server

    google-app-engine - App Engine 忽略我的源代码更新和我的 app.yaml 文件

    python - 打破pycharm中未处理的异常

    java - 源代码管理是否使 Javadoc 的 @author 和 @since 变得多余?

    version-control - 免费的 “Personal”源代码控制系统?

    backup - borg 备份 - 如何保留每周备份