Я могу восстановить свой исходный код, который был загружен в Google AppEngine?

Мне недавно разрушили жесткий диск и потерял весь мой исходный код. Действительно ли это возможно к получению по запросу/контролю код, который я уже загрузил на Google App Engine (как новая версия)?

16
задан Jon Seigel 1 April 2010 в 02:50
поделиться

3 ответа

Поскольку я только что потратил все силы на то, чтобы выяснить, как это сделать, я решил, что могу включить это в ответ, даже если это не относится к вам:

Прежде чем продолжить, поклянитесь могилой своей матери, что в следующий раз вы сделаете резервную копию своего кода, а лучше используйте контроль исходного кода. Я серьезно: Повторяйте за мной: "в следующий раз я буду использовать контроль исходников". Хорошо, с этим покончено, давайте посмотрим, возможно ли восстановить ваш код для вас...

Если ваше приложение было написано на Java, боюсь, вам не повезло - исходный код даже не загружается в App Engine для Java-приложений.

Если ваше приложение было написано на Python, и в нем были определены обработчики remote_api и deferred, есть возможность восстановить исходный код через взаимодействие этих двух API. Основной трюк выглядит так:

  1. Запуск remote_api_shell
  2. Создание новой отложенной задачи, которая считывает все ваши файлы и записывает их в хранилище данных
  3. Дождитесь выполнения этой задачи
  4. Извлечение ваших данных из хранилища данных с помощью remote_api

Смотрим по порядку:

Запуск remote_api_shell

Просто введите в командной строке следующее:

remote_api_shell.py your_app_id

Если оболочки нет в вашем пути, префикс команды обозначьте путем к директории 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' здесь является еще одним обходным путем для того, что мы не можем использовать утверждения: Выражение __import__('google.appengine.ext.db') импортирует ссылающийся модуль и возвращает модуль верхнего уровня (google).

Поскольку type() возвращает новый класс, у нас теперь есть подкласс Expando, который мы можем использовать для хранения данных в хранилище данных. Далее мы вызываем его конструктор, передавая ему два аргумента, 'name' и 'data'. Имя мы строим из конкатенации директории и файла, с которым мы сейчас работаем, а данные - это результат открытия этого имени файла и чтения его содержимого, обернутого в объект db.Text, поэтому они могут быть произвольной длины. Наконец, мы вызываем .put() для возвращенного экземпляра, чтобы сохранить его в хранилище данных.

Чтобы прочитать и сохранить весь исходный текст, а не только один файл, все это выражение выполняется внутри list comprehension, который итерирует сначала над результатом os.walk, который удобно возвращает все каталоги и файлы под базовым каталогом, а затем над каждым файлом в каждом из этих каталогов. Возвращаемое значение этого выражения - список ключей, которые были записаны в хранилище данных - просто отбрасывается отложенным модулем. Впрочем, это неважно, поскольку нас волнуют только побочные эффекты.

Наконец, мы вызываем функцию defer, откладывая вызов eval с только что описанным выражением в качестве аргумента.

Считывание данных

После выполнения вышеописанных действий и ожидания их завершения мы можем извлечь данные из хранилища данных, снова используя remote_api. Во-первых, нам нужна локальная версия модели codefile:

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, также не включены, и их нельзя восстановить - вам придется их переписать. Тем не менее, это гораздо лучше, чем переписывать все приложение, верно?

41
ответ дан 30 November 2019 в 15:05
поделиться

К сожалению, ответ отрицательный. Это частый вопрос на SO и на форумах, посвященных движку приложений. Смотрите здесь и здесь, например.

Я уверен, что с вами все будет в порядке, потому что вы ведь храните весь свой код в системе контроля исходных кодов, не так ли? ;)

Если вы хотите, чтобы это было возможно в будущем, вы можете загрузить zip-архив вашего src со ссылкой на него где-нибудь в вашем веб-приложении, как часть процесса сборки/развертывания.

Существуют также проекты, такие как этот, которые автоматизируют этот процесс для вас.

4
ответ дан 30 November 2019 в 15:05
поделиться

если вы используете python... вы могли бы написать скрипт, который открывает все файлы в текущем каталоге и дочерних каталогах и добавляет их в zip-файл для загрузки

Я не очень много знаю о app engine или разрешениях, но кажется, что это возможно

.
0
ответ дан 30 November 2019 в 15:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: