csbackgen.py 6.32 KB
Newer Older
1
2
#!/usr/bin/env python
## @file csbackgen.py
3
# @brief Generate checksum files.
4
5
6
7
8
9
10
# 
# -----------------------------------------------------------------------------
# 
# $Id$
# @author Daniel Armbruster
# \date 11/09/2011
# 
11
# Purpose: Generate checksum files.
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#
# ----
# This file is part of csback.
#
# csback is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# csback is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with csback.  If not, see <http://www.gnu.org/licenses/>.
# ----
# 
30
# Copyright (c) 2012 by Daniel Armbruster
31
32
# 
# REVISIONS and CHANGES 
33
# 02/01/2012  V0.1  Daniel Armbruster
34
35
36
# 
# =============================================================================
 
37
38
39
40
import getopt
import os
import sys
import re
41
import pwd
Daniel Armbruster's avatar
Daniel Armbruster committed
42
import logging
43
import csfile
44

45
46
47
48
49
__version__ = "V0.1"
__subversion__ = "$Id$"
__license__ = "GPLv2"
__author__ = "Daniel Armbruster"
__copyright__ = "Copyright (c) 2012 by Daniel Armbruster"
50

51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# -----------------------------------------------------------------------------
class Error(Exception):

  def __init__(self, msg):
    self.msg = msg

  def display(self):
    sys.stderr.write("csbackgen (ERROR): " + self.msg + "\n")


class Usage(Error):

  def display(self):
    usage_text = "Version: "+__version__+"\nLicense: "+__license__+ \
      "\n"+__subversion__+"\nAuthor: "+__author__+ """
 Usage: csbackgen [-v|--verbose] [-e REGEX [-e REGEX [...]]]
67
68
                  [-R|--notrecursive] [-d|--debug] [-f|--followlinks]
                  [-t|--target DIR] PATH
69
70
71
72
73
74
75
76
77
78
79
80
    or: csbackgen -h|--help\n"""
    sys.stderr.write("csbackgen: " + self.msg + "\n")
    sys.stderr.write(usage_text)

# -----------------------------------------------------------------------------
def help():
  """
  Printing helptext to stdout.
  """
  help_text = "Version: "+__version__+"\nLicense: "+__license__+"\n"+ \
    __subversion__+"\nAuthor: "+__author__+"""
 Usage: csbackgen [-v|--verbose] [-e REGEX [-e REGEX [...]]]
81
82
                  [-R|--notrecursive] [-d|--debug] [-f|--followlinks] 
                  [-t|--target DIR] PATH
83
84
85
86
87
    or: csbackgen -h|--help
-------------------------------------------------------------------------------
 -v|--verbose       Be verbose.
 -h|--help          Display this help.
 -e REGEX           While generating a checksumfile exclude files matching
Daniel Armbruster's avatar
Daniel Armbruster committed
88
                    REGEX(s).
89
90
91
92
 -R|--notrecursive  Do not generate checksumfiles for subdirectories.
 -d|--debug         Debug mode. Be really verbose.
 -f|--followlinks   Follow symbolic links. Only available if option -R is not
                    set. Note that this option can lead to infinite recursion.
93
 -t|--target        Target directory for checksumfile.
94
95
96
97
98
99
100
101
102
103
 PATH               Path to generate checksumfile for.
-------------------------------------------------------------------------------
csbackgen.py will either generate a checksumfile if still no checksumfile is
available or in case there is an existing checksumfile csbackgen.py will append
the not yet registered files to the current checksumfile. In the latter case
csbackgen.py is working in its update mode.\n"""
  sys.stdout.write(help_text)

# -----------------------------------------------------------------------------
def main(argv=None):
104
105
  # configure logger
  logInfo = {'hostname': os.uname()[1], \
106
    'user': pwd.getpwuid(os.getuid()).pw_name, \
107
    'pid': os.getpid()}
108
109
110
111
  csfile.csfileLogInfo = logInfo
  csfile.csfileLoggerName = 'csbackgen.csfile'
  log = logging.getLogger('csbackgen') 
  logger = logging.LoggerAdapter(log, logInfo)
112
  logging.basicConfig(level=logging.DEBUG, \
113
114
    format='%(asctime)-15s %(hostname)-6s %(name)-8s[%(pid)s]: \
(%(user)-4s) %(levelname)-8s %(message)s')
115
116
  console = logging.StreamHandler()
  formatter = logging.Formatter( \
117
    '%(name)-8s [%(lineno)d]: %(levelname)-8s %(message)s')
118
119
  console.setFormatter(formatter)

120
121
122
123
  if argv is None:
    argv = sys.argv
  try:
    try:
124
125
      opts, args = getopt.getopt(argv[1:], "vhe:Rdft:", ["help", "verbose", \
        "notrecursive", "debug", "followlinks", "target="])
126
127
128
129
130
131
132
    except getopt.GetoptError as err:
      raise Usage(err.msg)
    verbose = False
    debugMode = False
    notRecursive = False
    followLinks = False
    regexes = []
133
    targetSet = False
134
135
136
    for opt, arg in opts:
      if opt in ("-v", "--verbose"):
        verbose = True
137
        console.setLevel(logging.INFO)
138
139
140
141
142
143
144
145
      elif opt in ("-h", "--help"):
        sys.exit(help())
      elif opt in ("-R", "--notrecursive"):
        notRecursive = True
      elif opt in ("-e"):
        regexes.append(arg)
      elif opt in ("-d", "--debug"):
        debugMode = True
146
        console.setLevel(logging.DEBUG)
147
148
      elif opt in ("-f", "--followlinks"):
        followLinks = True
149
150
151
      elif opt in ("-t", "--target"):
        targetSet = True
        targetDirectory = str(arg)
152
153
      else:
        raise Usage("Unhandled option chosen.")
154
155

    if verbose or debugMode:
156
      log.addHandler(console)
157
158

    # fetch arguments   
159
    if 1 == len(args):
Daniel Armbruster's avatar
Daniel Armbruster committed
160
      inputpath = str(args[0]).rstrip(os.sep)+os.sep
161
162
    else:
      raise Usage("Invalid argument.")
Daniel Armbruster's avatar
Daniel Armbruster committed
163

164
165
166
167
168
169
    if not targetSet:
      targetDirectory = inputpath
    if not os.path.isdir(targetDirectory):
      raise Usage("Target directory not a valid directory.")

    # major part
Daniel Armbruster's avatar
Daniel Armbruster committed
170
171
    directories = [inputpath]
    if not notRecursive:
172
      logger.info("Collecting subdirectories.")
Daniel Armbruster's avatar
Daniel Armbruster committed
173
      directories.extend(csfile.getSubDirectories(inputpath, regexes, \
174
        followLinks))
Daniel Armbruster's avatar
Daniel Armbruster committed
175
    for dir in directories:
176
177
      logger.info("Update files in directory: %s to checksumfile: %s%s", dir, \
        targetDirectory, csfile.CsFile.filename)
Daniel Armbruster's avatar
Daniel Armbruster committed
178
      csfile.CsFile(targetDirectory, srcpath=dir).update(regexes)
Daniel Armbruster's avatar
Daniel Armbruster committed
179

180
181
182
183
184
185
186
  except Usage as err:
    err.display()
    return 2
  except csfile.CsFileError as err:
    err.display()
    return 2
  else:
Daniel Armbruster's avatar
Daniel Armbruster committed
187
    logger.info("Checksumfile updated.")
188
189
190
191
192
193
194
195
    return 0
    

# -----------------------------------------------------------------------------
if __name__ == "__main__":
  sys.exit(main())

# ----- END OF csbackgen.py -----