summaryrefslogtreecommitdiffstats
path: root/src/boost/tools/bcp/scan_cvs_path.cpp
blob: 6d2eb3a60005c97760387f58095473129ee06f5b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
 *
 * Copyright (c) 2003-7 John Maddock
 * Copyright (c) 2007 Bjorn Roald
 * Use, modification and distribution is subject to the 
 * Boost Software License, Version 1.0. (See accompanying file 
 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 *
 * This file implements the following:
 *    void bcp_implementation::scan_cvs_path(const fs::path& p)
 */



#include "bcp_imp.hpp"
#include "fileview.hpp"
#include <boost/regex.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/detail/workaround.hpp>
#include <iostream>

void bcp_implementation::scan_cvs_path(const fs::path& p)
{
   //
   // scan through the cvs admin files to build a list
   // of all the files under cvs version control
   // and whether they are text or binary:
   //
   static const char* file_list[] = { "CVS/Entries", "CVS/Entries.Log" };
   static const boost::regex file_expression("^(?:A\\s+)?/([^/\\n]+)/[^/\\n]*/[^/\\n]*/[^k/\\n]*(kb[^/\\n]*)?/[^/\\n]*");
   static const boost::regex dir_expression("^(?:A\\s+)?D/([^/\\n]+)/");
   static const int file_subs[] = {1,2,};

   for(std::size_t entry = 0; entry < sizeof(file_list)/sizeof(file_list[0]); ++entry)
   {
      fs::path entries(m_boost_path / p / file_list[entry]);
      if(fs::exists(entries))
      {
         fileview view(entries);
         boost::regex_token_iterator<const char*> i(view.begin(), view.end(), dir_expression, 1);
         boost::regex_token_iterator<const char*> j;
         while(i != j)
         {
            fs::path recursion_dir(p / i->str());
            scan_cvs_path(recursion_dir);
            ++i;
         }
   #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570))
         std::vector<int> v(file_subs, file_subs + 2);
         i = boost::regex_token_iterator<const char*>(view.begin(), view.end(), file_expression, v);
   #else
         i = boost::regex_token_iterator<const char*>(view.begin(), view.end(), file_expression, file_subs);
   #endif
         while(i != j)
         {
            fs::path file = p / i->str();
            ++i;
            bool binary = i->length() ? true : false;
            ++i;
            m_cvs_paths[file] = binary;
         }

      }
   }
}

void bcp_implementation::scan_svn_path(const fs::path& p)
{
   //
   // scan through the svn entries files to build a list
   // of all the files under svn version control
   // and whether they are text or binary:
   //
   static const boost::regex entry_expression("^\\f([^\\f]*)");
   static const boost::regex entry_line_expression("\\n[[:blank:]]*([^\\n]*)");
   //    static const boost::regex 
   //      mime_type_expression("\\nsvn:mime-type\\nV [[digit]]*\\n([^/]*)[^\\n]*");

   fs::path entries(m_boost_path / p / ".svn" / "entries");
   if(fs::exists(entries))
   {
      fileview view(entries);
      boost::cregex_token_iterator 
         i(view.begin(), view.end(), entry_expression, 1), j;

      while(i != j) // entries
      {
         std::string entr = i->str();
         boost::sregex_token_iterator
            atr_it(entr.begin(), entr.end(), entry_line_expression, 1), atr_j;       

         if(atr_it != atr_j) 
         {
            std::string name = atr_it->str(); // name of file or directory
            fs::path fpath = p / name;
            if(++atr_it != atr_j)
            {
               std::string kind = atr_it->str();
               if(kind == "file")
               {
                  // find if binary, we asume text unless mime type is 
                  // set in property file
                  bool binary = false;  // 

                  // skip some lines    type                   | example
                  if( ++atr_it != atr_j  &&  // revnum         |    
                     ++atr_it != atr_j  &&  // url            |
                     ++atr_it != atr_j  &&  // repos          |
                     ++atr_it != atr_j  &&  // scedule attr   |
                     ++atr_it != atr_j  &&  // text timestamp | 2007-09-02T...
                     ++atr_it != atr_j  &&  // checksum       | 58f4bfa7860...
                     ++atr_it != atr_j  &&  // cmt_date       | 2007-05-09T...
                     ++atr_it != atr_j  &&  // cmt_rev        | 37654
                     ++atr_it != atr_j  &&  // cmt_author     | dgregor
                     ++atr_it != atr_j )    // has_props      | has-props
                  {
                     if(atr_it->str() == "has-props")
                     {
                        // we  need to check properties file for mime-type
                        // that does not start with "text/", if found file is binary
                        fs::path properties(m_boost_path / p / ".svn" / "prop-base" 
                           / (name + ".svn-base") );
                        if(fs::exists(properties))
                        {
                           fileview prop(properties);

                           static const boost::regex mime_type(
                              "svn:mime-type[[:blank:]]*(?:\\n|\\r|\\r\\n)[^\\r\\n]*(?:\\n|\\r|\\r\\n)[[:blank:]]*text/");
                           binary = regex_search(prop.begin(), prop.end(), mime_type) ? false : true;
                        }
                     }
                  }
                  m_cvs_paths[fpath] = binary;
               }  // kind == "file"
               else if(kind == "dir")
               {
                  scan_svn_path(fpath); // recursion for directory entries
               }
               //       else
               //         std::cerr << "WARNING: unknown entry kind for entry " << name 
               //              << "in " << entries << std::endl;  
            }
         }
         ++i;
      } // while
   } 
}