csbackgen.py 5.91 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
Daniel Armbruster's avatar
Daniel Armbruster committed
41
import logging
42
import csfile
43

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

50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# -----------------------------------------------------------------------------
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 [...]]]
66
                  [-R|--notrecursive] [-d|--debug] [-f|--followlinks] PATH
67
68
69
70
71
72
73
74
75
76
77
78
    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 [...]]]
79
                  [-R|--notrecursive] [-d|--debug] [-f|--followlinks] PATH
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
    or: csbackgen -h|--help
-------------------------------------------------------------------------------
 -v|--verbose       Be verbose.
 -h|--help          Display this help.
 -e REGEX           While generating a checksumfile exclude files matching
                    REGEX.
 -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.
 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):
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
  # configure logger
  logInfo = {'hostname': os.uname()[1], \
    'user': str(pwd.getpwuid(os.getuid()).pw_name) \
    'pid': os.getpid()}
  csfile.__logInfo = logInfo
  csfile.moduleLoggerName = 'csbackgen.csfile'
  logger = logging.LoggerAdapter(logging.getLogger('csbackgen'), logInfo)
  logging.basicConfig(level=logging.DEBUG, \
    format='%(asctime)-15s %(hostname)-10s %(name)-15s[%(pid)-8s]: \
    (%(user)-8s) %(levelname)-8s %(message)s')
  console = logging.StreamHandler()
  formatter = logging.Formatter( \
    '%(name)-15s [%(lineno)d]: %(levelname)-15s %(message)s')
  console.setFormatter(formatter)

115
116
117
118
  if argv is None:
    argv = sys.argv
  try:
    try:
Daniel Armbruster's avatar
Daniel Armbruster committed
119
      opts, args = getopt.getopt(argv[1:], "vhe:Rdf", ["help", "verbose", \
120
121
122
123
124
125
126
127
128
129
130
        "notrecursive", "debug", "followlinks"])
    except getopt.GetoptError as err:
      raise Usage(err.msg)
    verbose = False
    debugMode = False
    notRecursive = False
    followLinks = False
    regexes = []
    for opt, arg in opts:
      if opt in ("-v", "--verbose"):
        verbose = True
131
        console.setLevel(logging.INFO)
132
133
134
135
136
137
138
139
      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
140
        console.setLevel(logging.DEBUG)
141
142
143
144
      elif opt in ("-f", "--followlinks"):
        followLinks = True
      else:
        raise Usage("Unhandled option chosen.")
145
146
147
148
149

    if verbose or debugMode:
      logger.addHandler(console)

    # fetch arguments   
150
    if 1 == len(args):
Daniel Armbruster's avatar
Daniel Armbruster committed
151
      inputpath = str(args[0]).rstrip(os.sep)+os.sep
152
153
    else:
      raise Usage("Invalid argument.")
Daniel Armbruster's avatar
Daniel Armbruster committed
154

155
    if notRecursive:
156
      logger.info("Generating checksumfile in: %s", inputpath)
157
158
      csfile.CsFile(inputpath).update(regexes)
    else:
159
      logger.info("Collecting subdirectories.")
160
      directories = [inputpath]
Daniel Armbruster's avatar
Daniel Armbruster committed
161
      directories.extend(csfile.getSubDirectories(inputpath, regexes, \
162
        followLinks))
163
      logger.info("Generating checksumfiles in subdirectories.")
164
165
      for dir in directories:
        csfile.CsFile(dir).update(regexes)
Daniel Armbruster's avatar
Daniel Armbruster committed
166

167
168
169
170
171
172
173
  except Usage as err:
    err.display()
    return 2
  except csfile.CsFileError as err:
    err.display()
    return 2
  else:
174
    logger.info("Checksumfile(s) updated.")
175
176
177
178
179
180
181
182
    return 0
    

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

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