Как добавить пустую папку в проект Mercurial?


44

В моем проекте я использую Mercurial и папку, в которой пользователь может загрузить файл. Но поскольку пользователь будет загружать файлы, папка пуста.

Я не знаю, как я могу добавить эту папку в свой проект, не помещая файл внутри.

Ты знаешь, как я могу это сделать?

Ответы:


46

Mercurial отслеживает только файлы , а не каталоги .

Одним из решений является добавление файла .empty в ваш репозиторий:

$ touch uploads/.empty
$ hg add uploads/.empty

1
Да, это действительно правильное решение: Mercurial отслеживает только файлы , а не каталоги. Другое решение заключается в создании пустых каталогов при развертывании программного обеспечения.
Мартин Гейслер

2
Я думаю, что наименование .hgemptyможет дать лучшую подсказку относительно того, для чего оно
Пользователь

8
Да или.hgkeep
Натим

2
С таким же успехом можно перейти к многословному: .hgkeepifempty :)
Даниэль Соколовский

4

Я создал скрипт Python, который автоматизирует процесс создания / удаления этих файлов.

Вот источник скрипта: http://pastebin.com/inbYmMut

#!/usr/bin/python

# Copyright (c) 2011 Ernesto Mendez (der-design.com)
# Dual licensed under the MIT and GPL licenses:
# http://www.opensource.org/licenses/mit-license.php
# http://www.gnu.org/licenses/gpl.html

# Version 1.0.0
# - Initial Release

from __future__ import generators
import sys
from optparse import OptionParser
import os

def main():
    # Process arguments

    if len(args) > 1:
        parser.error('Too many arguments')
        sys.exit()

    elif len(args) == 0:
        parser.error('Missing filename')
        sys.exit()

    if not os.path.exists(options.directory):
        parser.error("%s: No such directory" % options.directory)
        sys.exit()

    filename = args[0]

    # Create generator

    filetree = dirwalk(os.path.abspath(options.directory))

    # Walk directory tree, create files

    if options.remove == True:

        removed = ['Removing the following files: \n']
        cmd = "rm"

        for file in filetree:
            if (os.path.basename(file) == filename):
                removed.append(file)
                cmd += " %s" % fixpath(file)

        if cmd != "rm":
            for f in removed: print f
            os.system(cmd)
        else:
            print "No files named '%s' found" % filename
            sys.exit()

    # Walk directory tree, delete files

    else:

        created = ["Creating the following files:\n"]
        cmd = "touch"

        for file in filetree:
            if (os.path.isdir(file)):
                created.append("%s%s" % (file, filename))
                cmd += " " + fixpath("%s%s" % (file, filename))

        if cmd != "touch":
            for f in created: print f
            os.system(cmd)
        else:
            print "No empty directories found"
            sys.exit()


def dirwalk(dir, giveDirs=1):
    # http://code.activestate.com/recipes/105873-walk-a-directory-tree-using-a-generator/
    for f in os.listdir(dir):
        fullpath = os.path.join(dir, f)
        if os.path.isdir(fullpath) and not os.path.islink(fullpath):
            if not len(os.listdir(fullpath)):
                yield fullpath + os.sep
            else:
                for x in dirwalk(fullpath):  # recurse into subdir
                    if os.path.isdir(x):
                        if giveDirs:
                            yield x
                    else:
                        yield x
        else:
            yield fullpath


def wrap(text, width):
    return reduce(lambda line, word, width=width: '%s%s%s' % (line, ' \n'[(len(line)-line.rfind('\n')-1 + len(word.split('\n', 1)[0] ) >= width)], word), text.split(' ') )


def fixpath(p):
    return shellquote(os.path.normpath(p))


def shellquote(s):
    return "'" + s.replace("'", "'\\''") + "'"


def init_options():
    global parser, options, args
    parser = OptionParser(usage="usage: %prog [options] filename", description="Add or Remove placeholder files for SCM (Source Control Management) tools that do not support empty directories.")
    parser.add_option("-p", "--path", dest="directory", help="search within PATH", metavar="PATH")
    parser.add_option("-r", "--remove", dest="remove", action="store_true", help="remove FILE from PATH, if it's the only file on PATH")

    (options, args) = parser.parse_args()

if __name__ == '__main__':
    print
    init_options()
    main()
    print

Ссылка мертва.
Натим

Правда, обновленная ссылка ...
mendezcode

2
разместить его на bitbucket (или) github, старый pastebin старый
Phyo Arkar Lwin

-1, этот скрипт иллюстрирует nti-шаблоны и плохие практики.
Никратио

1

Вы просто делаете следующее:

mkdir images && touch images/.hgkeep
hg add images/.hgkeep
hg commit -m"Add the images folder as an empty folder"

Обратите внимание на следующее, когда вы делаете это:

В вашем случае вы можете загружать изображения в вашей среде разработки, поэтому я бы также рекомендовал добавить в ваш .hgignoreфайл следующее, чтобы вы не случайно зафиксировали изображения, которые вы не намеревались зафиксировать:

^(images)\/(?!\.hgkeep)

Правило будет игнорировать все, images/**кроме .hgkeepфайла, который вам нужен, чтобы добавить «пустую» папку в систему управления версиями. Причина, по которой это правило важно, заключается в том, что любые файлы в этой папке (т. Е. images/test-image.pngБудут выглядеть как новые не версионные файлы в вашей папке, hg statusесли вы не игнорируете этот шаблон).


2
Пожалуйста, внимательно прочитайте вопрос. Ваш ответ не отвечает на исходный вопрос, в котором спрашивается «как добавить пустую папку», а не «Как игнорировать папку»
DavidPostill

1
Вы правы. Я обновил свой ответ, чтобы фактически ответить на вопрос. Я изменил свой совет и оставил его, потому что в 99% случаев важно знать желаемое поведение.
Пол Редмонд

@PaulRedmond что если imagesкаталог находится глубоко в пути? Что то типа ./lectures/chapter_10/images? Какой тогда правильный синтаксис?
Арагон

@aaragon по общему признанию, это было некоторое время, так как я использовал Mercurial, но вам нужно будет настроить регулярное выражение, чтобы соответствовать шаблонам, которые вы намереваетесь. Когда вы заметите пути, которые, как вы ожидаете, будут игнорироваться, настройте регулярное выражение по мере необходимости.
Пол Редмонд
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.